1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-14 00:48:44 +01:00
dxvk/src/d3d11/d3d11_device.cpp

1898 lines
66 KiB
C++
Raw Normal View History

#include <algorithm>
2017-10-11 09:51:48 +02:00
#include <cstring>
2017-10-15 21:38:09 +02:00
#include "d3d11_buffer.h"
#include "d3d11_class_linkage.h"
#include "d3d11_context_def.h"
#include "d3d11_context_imm.h"
2017-10-11 09:51:48 +02:00
#include "d3d11_device.h"
#include "d3d11_input_layout.h"
#include "d3d11_present.h"
2017-12-29 22:20:31 +01:00
#include "d3d11_query.h"
2017-12-09 20:49:56 +01:00
#include "d3d11_sampler.h"
#include "d3d11_shader.h"
#include "d3d11_texture.h"
2017-10-11 09:51:48 +02:00
namespace dxvk {
D3D11Device::D3D11Device(
2017-11-27 15:51:53 +01:00
IDXGIDevicePrivate* dxgiDevice,
2017-10-11 09:51:48 +02:00
D3D_FEATURE_LEVEL featureLevel,
UINT featureFlags)
: m_dxgiDevice (dxgiDevice),
2017-12-04 13:39:37 +01:00
m_presentDevice (new D3D11PresentDevice()),
m_featureLevel (featureLevel),
m_featureFlags (featureFlags),
m_dxvkDevice (m_dxgiDevice->GetDXVKDevice()),
m_dxvkAdapter (m_dxvkDevice->adapter()),
m_dxbcOptions (m_dxvkDevice) {
Com<IDXGIAdapter> adapter;
if (FAILED(m_dxgiDevice->GetAdapter(&adapter))
|| FAILED(adapter->QueryInterface(__uuidof(IDXGIAdapterPrivate),
reinterpret_cast<void**>(&m_dxgiAdapter))))
throw DxvkError("D3D11Device: Failed to query adapter");
m_dxgiDevice->SetDeviceLayer(this);
m_presentDevice->SetDeviceLayer(this);
m_context = new D3D11ImmediateContext(this, m_dxvkDevice);
2018-01-13 05:00:27 +01:00
m_resourceInitContext = m_dxvkDevice->createContext();
2018-01-13 05:00:27 +01:00
m_resourceInitContext->beginRecording(
m_dxvkDevice->createCommandList());
CreateCounterBuffer();
2017-10-11 09:51:48 +02:00
}
D3D11Device::~D3D11Device() {
m_presentDevice->SetDeviceLayer(nullptr);
m_dxgiDevice->SetDeviceLayer(nullptr);
delete m_context;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::QueryInterface(REFIID riid, void** ppvObject) {
2017-10-15 21:50:34 +02:00
COM_QUERY_IFACE(riid, ppvObject, IUnknown);
2017-10-11 09:51:48 +02:00
COM_QUERY_IFACE(riid, ppvObject, ID3D11Device);
COM_QUERY_IFACE(riid, ppvObject, ID3D11Device1);
2017-10-11 09:51:48 +02:00
if (riid == __uuidof(IDXGIDevice)
|| riid == __uuidof(IDXGIDevice1)
|| riid == __uuidof(IDXGIDevice2)
|| riid == __uuidof(IDXGIDevicePrivate))
return m_dxgiDevice->QueryInterface(riid, ppvObject);
if (riid == __uuidof(IDXGIPresentDevicePrivate))
return m_presentDevice->QueryInterface(riid, ppvObject);
if (riid == __uuidof(ID3D11Debug))
return E_NOINTERFACE;
//d56e2a4c-5127-8437-658a-98c5bb789498, from GTA V, no occurrences in Google
if (riid == GUID{0xd56e2a4c,0x5127,0x8437,{0x65,0x8a,0x98,0xc5,0xbb,0x78,0x94,0x98}})
return E_NOINTERFACE;
2017-10-11 09:51:48 +02:00
Logger::warn("D3D11Device::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
2017-10-11 09:51:48 +02:00
return E_NOINTERFACE;
}
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) {
if (ppBuffer == nullptr)
return S_FALSE;
try {
const Com<D3D11Buffer> buffer
= new D3D11Buffer(this, pDesc);
2017-12-07 13:31:32 +01:00
this->InitBuffer(buffer.ptr(), pInitialData);
*ppBuffer = buffer.ref();
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::CreateTexture1D(
2017-10-11 09:51:48 +02:00
const D3D11_TEXTURE1D_DESC* pDesc,
const D3D11_SUBRESOURCE_DATA* pInitialData,
ID3D11Texture1D** ppTexture1D) {
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;
if (ppTexture1D == nullptr)
return S_FALSE;
try {
const Com<D3D11Texture1D> texture = new D3D11Texture1D(this, &desc);
this->InitTexture(texture->GetCommonTexture()->GetImage(), pInitialData);
*ppTexture1D = texture.ref();
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::CreateTexture2D(
2017-10-11 09:51:48 +02:00
const D3D11_TEXTURE2D_DESC* pDesc,
const D3D11_SUBRESOURCE_DATA* pInitialData,
ID3D11Texture2D** ppTexture2D) {
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;
if (ppTexture2D == nullptr)
return S_FALSE;
try {
const Com<D3D11Texture2D> texture = new D3D11Texture2D(this, &desc);
this->InitTexture(texture->GetCommonTexture()->GetImage(), pInitialData);
2017-12-19 16:01:50 +01:00
*ppTexture2D = texture.ref();
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) {
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;
if (ppTexture3D == nullptr)
return S_FALSE;
try {
const Com<D3D11Texture3D> texture = new D3D11Texture3D(this, &desc);
this->InitTexture(texture->GetCommonTexture()->GetImage(), pInitialData);
*ppTexture3D = texture.ref();
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::CreateShaderResourceView(
2017-10-11 09:51:48 +02:00
ID3D11Resource* pResource,
const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
ID3D11ShaderResourceView** ppSRView) {
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim);
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.
D3D11_SHADER_RESOURCE_VIEW_DESC desc;
if (pDesc == nullptr) {
if (FAILED(D3D11ShaderResourceView::GetDescFromResource(pResource, &desc)))
return E_INVALIDARG;
} else {
desc = *pDesc;
if (FAILED(D3D11ShaderResourceView::NormalizeDesc(pResource, &desc)))
return E_INVALIDARG;
}
if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
auto resource = static_cast<D3D11Buffer*>(pResource);
D3D11_BUFFER_DESC resourceDesc;
resource->GetDesc(&resourceDesc);
if ((resourceDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE) == 0) {
Logger::warn("D3D11: Trying to create SRV for buffer without D3D11_BIND_SHADER_RESOURCE");
return E_INVALIDARG;
}
DxvkBufferViewCreateInfo viewInfo;
D3D11_BUFFEREX_SRV bufInfo;
if (desc.ViewDimension == D3D11_SRV_DIMENSION_BUFFEREX) {
bufInfo.FirstElement = desc.BufferEx.FirstElement;
bufInfo.NumElements = desc.BufferEx.NumElements;
bufInfo.Flags = desc.BufferEx.Flags;
} else if (desc.ViewDimension == D3D11_SRV_DIMENSION_BUFFER) {
bufInfo.FirstElement = desc.Buffer.FirstElement;
bufInfo.NumElements = desc.Buffer.NumElements;
bufInfo.Flags = 0;
} else {
Logger::err("D3D11Device: Invalid buffer view dimension");
return E_INVALIDARG;
}
if (bufInfo.Flags & D3D11_BUFFEREX_SRV_FLAG_RAW) {
// Raw buffer view. We'll represent this as a
// uniform texel buffer with UINT32 elements.
viewInfo.format = VK_FORMAT_R32_UINT;
viewInfo.rangeOffset = sizeof(uint32_t) * bufInfo.FirstElement;
viewInfo.rangeLength = sizeof(uint32_t) * bufInfo.NumElements;
} else if (desc.Format == DXGI_FORMAT_UNKNOWN) {
// Structured buffer view
viewInfo.format = VK_FORMAT_R32_UINT;
viewInfo.rangeOffset = resourceDesc.StructureByteStride * bufInfo.FirstElement;
viewInfo.rangeLength = resourceDesc.StructureByteStride * bufInfo.NumElements;
} else {
// Typed buffer view - must use an uncompressed color format
viewInfo.format = m_dxgiAdapter->LookupFormat(
desc.Format, DxgiFormatMode::Color).format;
const DxvkFormatInfo* formatInfo = imageFormatInfo(viewInfo.format);
viewInfo.rangeOffset = formatInfo->elementSize * bufInfo.FirstElement;
viewInfo.rangeLength = formatInfo->elementSize * bufInfo.NumElements;
if (formatInfo->flags.test(DxvkFormatFlag::BlockCompressed)) {
Logger::err("D3D11Device: Compressed formats for buffer views not supported");
return E_INVALIDARG;
}
}
if (ppSRView == nullptr)
return S_FALSE;
try {
*ppSRView = ref(new D3D11ShaderResourceView(
this, pResource, desc,
m_dxvkDevice->createBufferView(
resource->GetBufferSlice().buffer(), viewInfo)));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return E_FAIL;
}
} else {
const D3D11CommonTexture* textureInfo = GetCommonTexture(pResource);
if ((textureInfo->Desc()->BindFlags & D3D11_BIND_SHADER_RESOURCE) == 0) {
Logger::warn("D3D11: Trying to create SRV for texture without D3D11_BIND_SHADER_RESOURCE");
return E_INVALIDARG;
}
2017-12-09 19:36:38 +01:00
// Fill in the view info. The view type depends solely
// on the view dimension field in the view description,
// not on the resource type.
2017-12-20 14:54:24 +01:00
const DxgiFormatInfo formatInfo = m_dxgiAdapter
->LookupFormat(desc.Format, textureInfo->GetFormatMode());
2017-12-20 14:54:24 +01:00
2017-12-09 19:36:38 +01:00
DxvkImageViewCreateInfo viewInfo;
2017-12-20 14:54:24 +01:00
viewInfo.format = formatInfo.format;
viewInfo.aspect = formatInfo.aspect;
viewInfo.swizzle = formatInfo.swizzle;
switch (desc.ViewDimension) {
case D3D11_SRV_DIMENSION_TEXTURE1D:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
viewInfo.minLevel = desc.Texture1D.MostDetailedMip;
viewInfo.numLevels = desc.Texture1D.MipLevels;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
viewInfo.minLevel = desc.Texture1DArray.MostDetailedMip;
viewInfo.numLevels = desc.Texture1DArray.MipLevels;
viewInfo.minLayer = desc.Texture1DArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture1DArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE2D:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = desc.Texture2D.MostDetailedMip;
viewInfo.numLevels = desc.Texture2D.MipLevels;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = desc.Texture2DArray.MostDetailedMip;
viewInfo.numLevels = desc.Texture2DArray.MipLevels;
viewInfo.minLayer = desc.Texture2DArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture2DArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DMS:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = desc.Texture2DMSArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture2DMSArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE3D:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_3D;
viewInfo.minLevel = desc.Texture3D.MostDetailedMip;
viewInfo.numLevels = desc.Texture3D.MipLevels;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_SRV_DIMENSION_TEXTURECUBE:
viewInfo.type = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
2017-12-09 19:36:38 +01:00
viewInfo.minLevel = desc.TextureCube.MostDetailedMip;
viewInfo.numLevels = desc.TextureCube.MipLevels;
viewInfo.minLayer = 0;
viewInfo.numLayers = 6;
break;
case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
viewInfo.minLevel = desc.TextureCubeArray.MostDetailedMip;
viewInfo.numLevels = desc.TextureCubeArray.MipLevels;
viewInfo.minLayer = desc.TextureCubeArray.First2DArrayFace;
viewInfo.numLayers = desc.TextureCubeArray.NumCubes * 6;
break;
default:
Logger::err(str::format(
"D3D11: View dimension not supported for SRV: ",
desc.ViewDimension));
return E_INVALIDARG;
}
2017-12-09 19:36:38 +01:00
if (ppSRView == nullptr)
return S_FALSE;
try {
2017-12-09 19:36:38 +01:00
*ppSRView = ref(new D3D11ShaderResourceView(
2017-12-27 01:36:45 +01:00
this, pResource, desc,
2017-12-09 19:36:38 +01:00
m_dxvkDevice->createImageView(
textureInfo->GetImage(),
viewInfo)));
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::CreateUnorderedAccessView(
2017-10-11 09:51:48 +02:00
ID3D11Resource* pResource,
const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
ID3D11UnorderedAccessView** ppUAView) {
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim);
// 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) {
if (FAILED(D3D11UnorderedAccessView::GetDescFromResource(pResource, &desc)))
return E_INVALIDARG;
} else {
desc = *pDesc;
if (FAILED(D3D11UnorderedAccessView::NormalizeDesc(pResource, &desc)))
return E_INVALIDARG;
}
if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
auto resource = static_cast<D3D11Buffer*>(pResource);
D3D11_BUFFER_DESC resourceDesc;
resource->GetDesc(&resourceDesc);
if ((resourceDesc.BindFlags & D3D11_BIND_UNORDERED_ACCESS) == 0) {
Logger::warn("D3D11: Trying to create UAV for buffer without D3D11_BIND_UNORDERED_ACCESS");
return E_INVALIDARG;
}
DxvkBufferViewCreateInfo viewInfo;
if (desc.Buffer.Flags & D3D11_BUFFEREX_SRV_FLAG_RAW) {
viewInfo.format = VK_FORMAT_R32_UINT;
viewInfo.rangeOffset = sizeof(uint32_t) * desc.Buffer.FirstElement;
viewInfo.rangeLength = sizeof(uint32_t) * desc.Buffer.NumElements;
} else if (desc.Format == DXGI_FORMAT_UNKNOWN) {
viewInfo.format = VK_FORMAT_R32_UINT;
viewInfo.rangeOffset = resourceDesc.StructureByteStride * desc.Buffer.FirstElement;
viewInfo.rangeLength = resourceDesc.StructureByteStride * desc.Buffer.NumElements;
} else {
// Typed buffer view - must use an uncompressed color format
viewInfo.format = m_dxgiAdapter->LookupFormat(
desc.Format, DxgiFormatMode::Color).format;
const DxvkFormatInfo* formatInfo = imageFormatInfo(viewInfo.format);
viewInfo.rangeOffset = formatInfo->elementSize * desc.Buffer.FirstElement;
viewInfo.rangeLength = formatInfo->elementSize * desc.Buffer.NumElements;
if (formatInfo->flags.test(DxvkFormatFlag::BlockCompressed)) {
Logger::err("D3D11Device: Compressed formats for buffer views not supported");
return E_INVALIDARG;
}
}
if (ppUAView == nullptr)
return S_FALSE;
try {
// Fetch a buffer slice for atomic
// append/consume functionality.
DxvkBufferSlice counterSlice;
if (desc.Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER))
counterSlice = AllocateCounterSlice();
*ppUAView = ref(new D3D11UnorderedAccessView(
this, pResource, desc,
m_dxvkDevice->createBufferView(
resource->GetBufferSlice().buffer(), viewInfo),
counterSlice));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return E_FAIL;
}
} else {
const D3D11CommonTexture* textureInfo = GetCommonTexture(pResource);
2018-01-01 19:46:19 +01:00
if ((textureInfo->Desc()->BindFlags & D3D11_BIND_UNORDERED_ACCESS) == 0) {
Logger::warn("D3D11: Trying to create UAV for texture without D3D11_BIND_UNORDERED_ACCESS");
return E_INVALIDARG;
}
2018-01-01 19:46:19 +01:00
// Fill in the view info. The view type depends solely
// on the view dimension field in the view description,
// not on the resource type.
const DxgiFormatInfo formatInfo = m_dxgiAdapter
->LookupFormat(desc.Format, textureInfo->GetFormatMode());
2018-01-01 19:46:19 +01:00
DxvkImageViewCreateInfo viewInfo;
viewInfo.format = formatInfo.format;
viewInfo.aspect = formatInfo.aspect;
viewInfo.swizzle = formatInfo.swizzle;
switch (desc.ViewDimension) {
case D3D11_UAV_DIMENSION_TEXTURE1D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
viewInfo.minLevel = desc.Texture1D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_UAV_DIMENSION_TEXTURE1DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
viewInfo.minLevel = desc.Texture1DArray.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = desc.Texture1DArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture1DArray.ArraySize;
break;
case D3D11_UAV_DIMENSION_TEXTURE2D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = desc.Texture2D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_UAV_DIMENSION_TEXTURE2DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = desc.Texture2DArray.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = desc.Texture2DArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture2DArray.ArraySize;
break;
case D3D11_UAV_DIMENSION_TEXTURE3D:
// FIXME we actually have to map this to a
// 2D array view in order to support W slices
2018-01-01 19:46:19 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_3D;
viewInfo.minLevel = desc.Texture3D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
default:
Logger::err(str::format(
"D3D11: View dimension not supported for UAV: ",
2018-01-01 19:46:19 +01:00
desc.ViewDimension));
return E_INVALIDARG;
}
if (ppUAView == nullptr)
return S_FALSE;
try {
*ppUAView = ref(new D3D11UnorderedAccessView(
this, pResource, desc,
m_dxvkDevice->createImageView(
textureInfo->GetImage(),
viewInfo),
DxvkBufferSlice()));
2018-01-01 19:46:19 +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::CreateRenderTargetView(
2017-10-11 09:51:48 +02:00
ID3D11Resource* pResource,
const D3D11_RENDER_TARGET_VIEW_DESC* pDesc,
ID3D11RenderTargetView** ppRTView) {
// DXVK only supports render target views for image resources
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim);
if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
Logger::err("D3D11: Cannot create render target view for a buffer");
return E_INVALIDARG;
}
// The view description is optional. If not defined, it
// will use the resource's format and all array layers.
D3D11_RENDER_TARGET_VIEW_DESC desc;
2017-12-09 19:36:38 +01:00
if (pDesc == nullptr) {
if (FAILED(D3D11RenderTargetView::GetDescFromResource(pResource, &desc)))
2017-12-09 19:36:38 +01:00
return E_INVALIDARG;
} else {
2017-12-09 19:36:38 +01:00
desc = *pDesc;
if (FAILED(D3D11RenderTargetView::NormalizeDesc(pResource, &desc)))
return E_INVALIDARG;
}
2017-12-09 19:36:38 +01:00
// Retrieve the image that we are going to create the view for
const D3D11CommonTexture* textureInfo = GetCommonTexture(pResource);
2017-12-09 19:36:38 +01:00
if ((textureInfo->Desc()->BindFlags & D3D11_BIND_RENDER_TARGET) == 0) {
Logger::warn("D3D11: Trying to create RTV for texture without D3D11_BIND_RENDER_TARGET");
return E_INVALIDARG;
}
// Fill in Vulkan image view info
DxvkImageViewCreateInfo viewInfo;
2017-12-20 14:54:24 +01:00
viewInfo.format = m_dxgiAdapter->LookupFormat(desc.Format, DxgiFormatMode::Color).format;
2017-12-09 02:44:59 +01:00
viewInfo.aspect = imageFormatInfo(viewInfo.format)->aspectMask;
switch (desc.ViewDimension) {
case D3D11_RTV_DIMENSION_TEXTURE1D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
viewInfo.minLevel = desc.Texture1D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
viewInfo.minLevel = desc.Texture1DArray.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = desc.Texture1DArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture1DArray.ArraySize;
break;
case D3D11_RTV_DIMENSION_TEXTURE2D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = desc.Texture2D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = desc.Texture2DArray.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = desc.Texture2DArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture2DArray.ArraySize;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DMS:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = desc.Texture2DMSArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture2DMSArray.ArraySize;
break;
case D3D11_RTV_DIMENSION_TEXTURE3D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = desc.Texture3D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = desc.Texture3D.FirstWSlice;
viewInfo.numLayers = desc.Texture3D.WSize;
break;
default:
Logger::err(str::format(
"D3D11: pDesc->ViewDimension not supported for render target views: ",
desc.ViewDimension));
return E_INVALIDARG;
}
// Create the actual image view if requested
if (ppRTView == nullptr)
return S_FALSE;
try {
*ppRTView = ref(new D3D11RenderTargetView(
2017-12-27 01:36:45 +01:00
this, pResource, desc,
2017-12-09 19:36:38 +01:00
m_dxvkDevice->createImageView(
textureInfo->GetImage(),
viewInfo)));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return E_FAIL;
}
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateDepthStencilView(
ID3D11Resource* pResource,
const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc,
ID3D11DepthStencilView** ppDepthStencilView) {
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim);
// 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) {
if (FAILED(D3D11DepthStencilView::GetDescFromResource(pResource, &desc)))
2017-12-09 19:36:38 +01:00
return E_INVALIDARG;
} else {
2017-12-09 19:36:38 +01:00
desc = *pDesc;
if (FAILED(D3D11DepthStencilView::NormalizeDesc(pResource, &desc)))
return E_INVALIDARG;
}
2017-12-09 19:36:38 +01:00
// Retrieve the image that we are going to create the view for
const D3D11CommonTexture* textureInfo = GetCommonTexture(pResource);
2017-12-09 19:36:38 +01:00
if ((textureInfo->Desc()->BindFlags & D3D11_BIND_DEPTH_STENCIL) == 0) {
Logger::warn("D3D11: Trying to create DSV for texture without D3D11_BIND_DEPTH_STENCIL");
return E_INVALIDARG;
}
// Fill in Vulkan image view info
DxvkImageViewCreateInfo viewInfo;
2017-12-20 14:54:24 +01:00
viewInfo.format = m_dxgiAdapter->LookupFormat(desc.Format, DxgiFormatMode::Depth).format;
2017-12-09 02:44:59 +01:00
viewInfo.aspect = imageFormatInfo(viewInfo.format)->aspectMask;
switch (desc.ViewDimension) {
case D3D11_DSV_DIMENSION_TEXTURE1D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
viewInfo.minLevel = desc.Texture1D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
viewInfo.minLevel = desc.Texture1DArray.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = desc.Texture1DArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture1DArray.ArraySize;
break;
case D3D11_DSV_DIMENSION_TEXTURE2D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = desc.Texture2D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = desc.Texture2DArray.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = desc.Texture2DArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture2DArray.ArraySize;
break;
case D3D11_DSV_DIMENSION_TEXTURE2DMS:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = desc.Texture2DMSArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture2DMSArray.ArraySize;
break;
default:
Logger::err(str::format(
"D3D11: pDesc->ViewDimension not supported for depth-stencil views: ",
desc.ViewDimension));
return E_INVALIDARG;
}
// Create the actual image view if requested
if (ppDepthStencilView == nullptr)
return S_FALSE;
try {
*ppDepthStencilView = ref(new D3D11DepthStencilView(
2017-12-27 01:36:45 +01:00
this, pResource, desc,
2017-12-09 19:36:38 +01:00
m_dxvkDevice->createImageView(
textureInfo->GetImage(),
viewInfo)));
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::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) {
try {
DxbcReader dxbcReader(reinterpret_cast<const char*>(
pShaderBytecodeWithInputSignature), BytecodeLength);
DxbcModule dxbcModule(dxbcReader);
const Rc<DxbcIsgn> inputSignature = dxbcModule.isgn();
2017-12-08 00:44:58 +01:00
std::vector<DxvkVertexAttribute> attributes;
std::vector<DxvkVertexBinding> bindings;
for (uint32_t i = 0; i < NumElements; i++) {
const DxbcSgnEntry* entry = inputSignature->find(
pInputElementDescs[i].SemanticName,
pInputElementDescs[i].SemanticIndex);
if (entry == nullptr) {
Logger::debug(str::format(
2018-01-02 12:07:30 +01:00
"D3D11Device: No such vertex shader semantic: ",
pInputElementDescs[i].SemanticName,
pInputElementDescs[i].SemanticIndex));
continue;
}
// Create vertex input attribute description
2017-12-08 00:44:58 +01:00
DxvkVertexAttribute attrib;
attrib.location = entry->registerId;
attrib.binding = pInputElementDescs[i].InputSlot;
attrib.format = m_dxgiAdapter->LookupFormat(
2017-12-20 14:54:24 +01:00
pInputElementDescs[i].Format, DxgiFormatMode::Color).format;
attrib.offset = pInputElementDescs[i].AlignedByteOffset;
// 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.
if (attrib.offset == D3D11_APPEND_ALIGNED_ELEMENT) {
attrib.offset = 0;
for (uint32_t j = 1; j <= i; j++) {
const DxvkVertexAttribute& prev = attributes.at(i - j);
if (prev.binding == attrib.binding) {
const DxvkFormatInfo* formatInfo = imageFormatInfo(prev.format);
attrib.offset = align(prev.offset + formatInfo->elementSize, 4);
break;
}
}
}
attributes.push_back(attrib);
// Create vertex input binding description. The
// stride is dynamic state in D3D11 and will be
// set by D3D11DeviceContext::IASetVertexBuffers.
2017-12-08 00:44:58 +01:00
DxvkVertexBinding binding;
binding.binding = pInputElementDescs[i].InputSlot;
binding.fetchRate = pInputElementDescs[i].InstanceDataStepRate;
binding.inputRate = pInputElementDescs[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA
? VK_VERTEX_INPUT_RATE_INSTANCE
: VK_VERTEX_INPUT_RATE_VERTEX;
// Check if the binding was already defined. If so, the
// parameters must be identical (namely, the input rate).
bool bindingDefined = false;
for (const auto& existingBinding : bindings) {
if (binding.binding == existingBinding.binding) {
bindingDefined = true;
if (binding.inputRate != existingBinding.inputRate) {
Logger::err(str::format(
"D3D11Device: Conflicting input rate for binding ",
binding.binding));
return E_INVALIDARG;
}
}
}
if (!bindingDefined)
bindings.push_back(binding);
}
// 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;
for (uint32_t j = 0; j < attributes.size() && !found; j++)
found = attributes.at(j).location == i->registerId;
if (!found) {
Logger::warn(str::format(
"D3D11Device: Vertex input '",
i->semanticName, i->semanticIndex,
"' not defined by input layout"));
}
}
std::sort(bindings.begin(), bindings.end(),
[] (const DxvkVertexBinding& a, const DxvkVertexBinding& b) {
return a.binding < b.binding;
});
// Create the actual input layout object
// if the application requests it.
if (ppInputLayout != nullptr) {
*ppInputLayout = ref(
new D3D11InputLayout(this,
2017-12-08 00:44:58 +01:00
attributes.size(),
attributes.data(),
bindings.size(),
bindings.data()));
}
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::CreateVertexShader(
2017-10-11 09:51:48 +02:00
const void* pShaderBytecode,
SIZE_T BytecodeLength,
ID3D11ClassLinkage* pClassLinkage,
ID3D11VertexShader** ppVertexShader) {
D3D11ShaderModule module;
if (FAILED(this->CreateShaderModule(&module,
pShaderBytecode, BytecodeLength, pClassLinkage)))
return E_INVALIDARG;
if (ppVertexShader == nullptr)
return S_FALSE;
*ppVertexShader = ref(new D3D11VertexShader(
this, std::move(module)));
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) {
2017-12-18 12:53:53 +01:00
D3D11ShaderModule module;
if (FAILED(this->CreateShaderModule(&module,
pShaderBytecode, BytecodeLength, pClassLinkage)))
return E_INVALIDARG;
if (ppGeometryShader == nullptr)
return S_FALSE;
2017-12-18 12:53:53 +01:00
*ppGeometryShader = ref(new D3D11GeometryShader(
this, std::move(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) {
Logger::err("D3D11Device::CreateGeometryShaderWithStreamOutput: Not implemented");
return E_NOTIMPL;
}
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) {
D3D11ShaderModule module;
if (FAILED(this->CreateShaderModule(&module,
pShaderBytecode, BytecodeLength, pClassLinkage)))
return E_INVALIDARG;
if (ppPixelShader == nullptr)
return S_FALSE;
*ppPixelShader = ref(new D3D11PixelShader(
this, std::move(module)));
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) {
D3D11ShaderModule module;
if (FAILED(this->CreateShaderModule(&module,
pShaderBytecode, BytecodeLength, pClassLinkage)))
return E_INVALIDARG;
if (ppHullShader == nullptr)
return S_FALSE;
*ppHullShader = ref(new D3D11HullShader(
this, std::move(module)));
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) {
D3D11ShaderModule module;
if (FAILED(this->CreateShaderModule(&module,
pShaderBytecode, BytecodeLength, pClassLinkage)))
return E_INVALIDARG;
if (ppDomainShader == nullptr)
return S_FALSE;
*ppDomainShader = ref(new D3D11DomainShader(
this, std::move(module)));
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) {
2017-12-21 17:27:40 +01:00
D3D11ShaderModule module;
if (FAILED(this->CreateShaderModule(&module,
pShaderBytecode, BytecodeLength, pClassLinkage)))
return E_INVALIDARG;
if (ppComputeShader == nullptr)
return S_FALSE;
2017-12-21 17:27:40 +01:00
*ppComputeShader = ref(new D3D11ComputeShader(
this, std::move(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) {
*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-03-18 23:27:29 +01:00
D3D11_BLEND_DESC1 desc = pBlendStateDesc != nullptr
? D3D11BlendState::PromoteDesc(pBlendStateDesc)
: D3D11BlendState::DefaultDesc();
2018-03-18 23:27:29 +01:00
if (FAILED(D3D11BlendState::NormalizeDesc(&desc)))
return E_INVALIDARG;
if (ppBlendState != nullptr) {
*ppBlendState = m_bsStateObjects.Create(this, desc);
return S_OK;
} return S_FALSE;
2017-10-11 09:51:48 +02:00
}
HRESULT STDMETHODCALLTYPE D3D11Device::CreateBlendState1(
const D3D11_BLEND_DESC1* pBlendStateDesc,
ID3D11BlendState1** 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;
}
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) {
D3D11_DEPTH_STENCIL_DESC desc = pDepthStencilDesc != nullptr
? *pDepthStencilDesc
: D3D11DepthStencilState::DefaultDesc();
if (FAILED(D3D11DepthStencilState::NormalizeDesc(&desc)))
return E_INVALIDARG;
if (ppDepthStencilState != nullptr) {
*ppDepthStencilState = m_dsStateObjects.Create(this, desc);
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) {
D3D11_RASTERIZER_DESC1 desc = pRasterizerDesc != nullptr
? D3D11RasterizerState::PromoteDesc(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;
2017-10-11 09:51:48 +02:00
}
HRESULT D3D11Device::CreateRasterizerState1(
const D3D11_RASTERIZER_DESC1* pRasterizerDesc,
ID3D11RasterizerState1** ppRasterizerState) {
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;
}
2017-10-11 09:51:48 +02: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) {
D3D11_SAMPLER_DESC desc = *pSamplerDesc;
2017-12-09 20:49:56 +01:00
if (FAILED(D3D11SamplerState::NormalizeDesc(&desc)))
return E_INVALIDARG;
2017-12-09 20:49:56 +01:00
if (ppSamplerState == nullptr)
return S_FALSE;
2017-12-09 20:49:56 +01:00
try {
*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());
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-02-18 22:34:23 +01:00
if (pQueryDesc->Query != D3D11_QUERY_EVENT
&& pQueryDesc->Query != D3D11_QUERY_OCCLUSION
&& pQueryDesc->Query != D3D11_QUERY_TIMESTAMP
&& pQueryDesc->Query != D3D11_QUERY_TIMESTAMP_DISJOINT
&& pQueryDesc->Query != D3D11_QUERY_PIPELINE_STATISTICS
&& pQueryDesc->Query != D3D11_QUERY_OCCLUSION_PREDICATE) {
Logger::warn(str::format("D3D11Query: Unsupported query type ", pQueryDesc->Query));
return E_INVALIDARG;
}
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 {
*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-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) {
Logger::err("D3D11Device::CreateCounter: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateDeferredContext(
2017-10-11 09:51:48 +02:00
UINT ContextFlags,
ID3D11DeviceContext** ppDeferredContext) {
*ppDeferredContext = ref(new D3D11DeferredContext(this, m_dxvkDevice, ContextFlags));
return S_OK;
2017-10-11 09:51:48 +02: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) {
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) {
Logger::err("D3D11Device::OpenSharedResource: Not implemented");
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE D3D11Device::OpenSharedResource1(
HANDLE hResource,
REFIID ReturnedInterface,
void** ppResource) {
Logger::err("D3D11Device::OpenSharedResource1: Not implemented");
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE D3D11Device::OpenSharedResourceByName(
LPCWSTR lpName,
DWORD dwDesiredAccess,
REFIID returnedInterface,
void ** ppResource) {
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) {
return GetFormatSupportFlags(Format, pFormatSupport);
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) {
// 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.
*pNumQualityLevels = 0;
// We need to check whether the format is
VkFormat format = m_dxgiAdapter->LookupFormat(
2017-12-20 14:54:24 +01:00
Format, DxgiFormatMode::Any).format;
if (format == VK_FORMAT_UNDEFINED) {
Logger::err(str::format("D3D11: Unsupported format: ", Format));
return E_INVALIDARG;
}
// D3D may legally query non-power-of-two sample counts as well
VkSampleCountFlagBits sampleCountFlag = VK_SAMPLE_COUNT_1_BIT;
if (FAILED(GetSampleCount(SampleCount, &sampleCountFlag)))
return E_INVALIDARG;
// 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.
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) {
2017-10-11 09:51:48 +02:00
Logger::err("D3D11Device::CheckCounterInfo: Not implemented");
}
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) {
Logger::err("D3D11Device::CheckCounter: Not implemented");
return E_NOTIMPL;
}
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) {
switch (Feature) {
case D3D11_FEATURE_THREADING: {
if (FeatureSupportDataSize != sizeof(D3D11_FEATURE_DATA_THREADING))
return E_INVALIDARG;
auto info = static_cast<D3D11_FEATURE_DATA_THREADING*>(pFeatureSupportData);
info->DriverConcurrentCreates = TRUE;
info->DriverCommandLists = FALSE;
} 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);
info->DoublePrecisionFloatShaderOps = FALSE;
} 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);
return GetFormatSupportFlags(info->InFormat, &info->OutFormatSupport);
} return S_OK;
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;
case D3D11_FEATURE_D3D11_OPTIONS: {
if (FeatureSupportDataSize != sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS))
return E_INVALIDARG;
auto info = static_cast<D3D11_FEATURE_DATA_D3D11_OPTIONS*>(pFeatureSupportData);
/*TODO: implement and enable*/
/*https://msdn.microsoft.com/en-us/library/windows/desktop/hh404457(v=vs.85).aspx */
info->OutputMergerLogicOp = false;
info->UAVOnlyRenderingForcedSampleCount = false;
info->DiscardAPIsSeenByDriver = false;
info->FlagsForUpdateAndCopySeenByDriver = false;
info->ClearView = false;
info->CopyWithOverlap = false;
info->ConstantBufferPartialUpdate = false;
info->ConstantBufferOffsetting = false;
info->MapNoOverwriteOnDynamicConstantBuffer = false;
info->MapNoOverwriteOnDynamicBufferSRV = false;
info->MultisampleRTVWithForcedSampleCountOne = false;
info->SAD4ShaderInstructions = false;
info->ExtendedDoublesShaderInstructions = false;
info->ExtendedResourceSharing = false;
} 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);
info->TileBasedDeferredRenderer = false;
} return S_OK;
default:
Logger::err(str::format(
"D3D11Device: CheckFeatureSupport: Unknown feature: ",
Feature));
return E_INVALIDARG;
}
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) {
return m_dxgiDevice->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) {
return m_dxgiDevice->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) {
return m_dxgiDevice->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() {
static std::atomic<bool> s_errorShown = { false };
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) {
*ppImmediateContext = ref(m_context);
2017-10-11 09:51:48 +02: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-12-20 14:54:24 +01:00
DxgiFormatInfo STDMETHODCALLTYPE D3D11Device::LookupFormat(
2017-12-19 16:01:50 +01:00
DXGI_FORMAT format,
DxgiFormatMode mode) const {
return m_dxgiAdapter->LookupFormat(format, mode);
}
DxvkBufferSlice D3D11Device::AllocateCounterSlice() {
std::lock_guard<std::mutex> lock(m_counterMutex);
if (m_counterSlices.size() == 0)
throw DxvkError("D3D11Device: Failed to allocate counter slice");
uint32_t sliceId = m_counterSlices.back();
m_counterSlices.pop_back();
return DxvkBufferSlice(m_counterBuffer,
sizeof(D3D11UavCounter) * sliceId,
sizeof(D3D11UavCounter));
}
void D3D11Device::FreeCounterSlice(const DxvkBufferSlice& Slice) {
std::lock_guard<std::mutex> lock(m_counterMutex);
m_counterSlices.push_back(Slice.offset() / sizeof(D3D11UavCounter));
}
2018-01-13 05:00:27 +01:00
void D3D11Device::FlushInitContext() {
LockResourceInitContext();
if (m_resourceInitCommands != 0)
SubmitResourceInitCommands();
UnlockResourceInitContext(0);
2018-01-13 05:00:27 +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;
if (m_dxvkDevice->features().geometryShader)
enabledShaderPipelineStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
if (m_dxvkDevice->features().tessellationShader) {
enabledShaderPipelineStages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
| VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
}
return enabledShaderPipelineStages;
}
bool D3D11Device::CheckFeatureLevelSupport(
const Rc<DxvkAdapter>& adapter,
D3D_FEATURE_LEVEL featureLevel) {
// We currently only support 11_0 interfaces
if (featureLevel > GetMaxFeatureLevel())
return false;
// Check whether all features are supported
const VkPhysicalDeviceFeatures features
= GetDeviceFeatures(adapter, featureLevel);
if (!adapter->checkFeatureSupport(features))
return false;
// TODO also check for required limits
return true;
}
VkPhysicalDeviceFeatures D3D11Device::GetDeviceFeatures(
const Rc<DxvkAdapter>& adapter,
D3D_FEATURE_LEVEL featureLevel) {
VkPhysicalDeviceFeatures supported = adapter->features();
VkPhysicalDeviceFeatures enabled = {};
if (featureLevel >= D3D_FEATURE_LEVEL_9_1) {
enabled.depthClamp = VK_TRUE;
enabled.depthBiasClamp = VK_TRUE;
enabled.fillModeNonSolid = VK_TRUE;
enabled.pipelineStatisticsQuery = supported.pipelineStatisticsQuery;
enabled.sampleRateShading = VK_TRUE;
enabled.samplerAnisotropy = VK_TRUE;
enabled.shaderClipDistance = VK_TRUE;
enabled.shaderCullDistance = VK_TRUE;
enabled.robustBufferAccess = VK_TRUE;
}
if (featureLevel >= D3D_FEATURE_LEVEL_9_2) {
enabled.occlusionQueryPrecise = VK_TRUE;
}
if (featureLevel >= D3D_FEATURE_LEVEL_9_3) {
enabled.multiViewport = VK_TRUE;
enabled.independentBlend = VK_TRUE;
}
if (featureLevel >= D3D_FEATURE_LEVEL_10_0) {
enabled.fullDrawIndexUint32 = VK_TRUE;
enabled.fragmentStoresAndAtomics = VK_TRUE;
enabled.geometryShader = VK_TRUE;
enabled.logicOp = supported.logicOp;
enabled.shaderImageGatherExtended = VK_TRUE;
enabled.textureCompressionBC = VK_TRUE;
enabled.vertexPipelineStoresAndAtomics = VK_TRUE;
}
if (featureLevel >= D3D_FEATURE_LEVEL_10_1) {
enabled.dualSrcBlend = VK_TRUE;
enabled.imageCubeArray = VK_TRUE;
}
if (featureLevel >= D3D_FEATURE_LEVEL_11_0) {
enabled.shaderFloat64 = supported.shaderFloat64;
enabled.shaderInt64 = supported.shaderInt64;
enabled.tessellationShader = VK_TRUE;
enabled.shaderStorageImageReadWithoutFormat = VK_TRUE;
enabled.shaderStorageImageWriteWithoutFormat = VK_TRUE;
}
return enabled;
}
HRESULT D3D11Device::CreateShaderModule(
D3D11ShaderModule* pShaderModule,
const void* pShaderBytecode,
size_t BytecodeLength,
ID3D11ClassLinkage* pClassLinkage) {
if (pClassLinkage != nullptr)
Logger::warn("D3D11Device::CreateShaderModule: Class linkage not supported");
try {
*pShaderModule = D3D11ShaderModule(
&m_dxbcOptions, this, pShaderBytecode, BytecodeLength);
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return E_FAIL;
}
}
void D3D11Device::InitBuffer(
D3D11Buffer* pBuffer,
const D3D11_SUBRESOURCE_DATA* pInitialData) {
const DxvkBufferSlice bufferSlice
2017-12-15 19:11:10 +01:00
= pBuffer->GetBufferSlice();
if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
LockResourceInitContext();
2018-01-13 05:00:27 +01:00
m_resourceInitContext->updateBuffer(
bufferSlice.buffer(),
bufferSlice.offset(),
bufferSlice.length(),
pInitialData->pSysMem);
UnlockResourceInitContext(1);
}
}
2017-12-08 23:13:15 +01:00
void D3D11Device::InitTexture(
const Rc<DxvkImage>& image,
2017-12-08 23:13:15 +01:00
const D3D11_SUBRESOURCE_DATA* pInitialData) {
const DxvkFormatInfo* formatInfo = imageFormatInfo(image->info().format);
2017-12-08 23:13:15 +01:00
if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
LockResourceInitContext();
// pInitialData is an array that stores an entry for
// every single subresource. Since we will define all
// subresources, this counts as initialization.
VkImageSubresourceLayers subresourceLayers;
subresourceLayers.aspectMask = formatInfo->aspectMask;
subresourceLayers.mipLevel = 0;
subresourceLayers.baseArrayLayer = 0;
subresourceLayers.layerCount = 1;
for (uint32_t layer = 0; layer < image->info().numLayers; layer++) {
for (uint32_t level = 0; level < image->info().mipLevels; level++) {
subresourceLayers.baseArrayLayer = layer;
subresourceLayers.mipLevel = level;
const uint32_t id = D3D11CalcSubresource(
level, layer, image->info().mipLevels);
m_resourceInitContext->updateImage(
image, subresourceLayers,
VkOffset3D { 0, 0, 0 },
image->mipLevelExtent(level),
pInitialData[id].pSysMem,
pInitialData[id].SysMemPitch,
pInitialData[id].SysMemSlicePitch);
}
}
const uint32_t subresourceCount =
image->info().numLayers * image->info().mipLevels;
UnlockResourceInitContext(subresourceCount);
} else {
LockResourceInitContext();
// While the Microsoft docs state that resource contents are
// undefined if no initial data is provided, some applications
// expect a resource to be pre-cleared. We can only do that
// for non-compressed images, but that should be fine.
VkImageSubresourceRange subresources;
subresources.aspectMask = formatInfo->aspectMask;
subresources.baseMipLevel = 0;
subresources.levelCount = image->info().mipLevels;
subresources.baseArrayLayer = 0;
subresources.layerCount = image->info().numLayers;
const DxvkFormatInfo* formatInfo = imageFormatInfo(image->info().format);
if (formatInfo->flags.test(DxvkFormatFlag::BlockCompressed)) {
m_resourceInitContext->initImage(
image, subresources);
} else {
if (subresources.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
m_resourceInitContext->clearColorImage(
image, VkClearColorValue(), subresources);
} else {
VkClearDepthStencilValue value;
value.depth = 1.0f;
value.stencil = 0;
m_resourceInitContext->clearDepthStencilImage(
image, value, subresources);
}
}
UnlockResourceInitContext(1);
}
2017-12-08 23:13:15 +01:00
}
HRESULT D3D11Device::GetFormatSupportFlags(DXGI_FORMAT Format, UINT* pFlags) const {
2017-12-20 14:54:24 +01:00
const VkFormat fmt = m_dxgiAdapter->LookupFormat(Format, DxgiFormatMode::Any).format;
const VkFormatProperties fmtInfo = m_dxvkAdapter->formatProperties(fmt);
if (fmt == VK_FORMAT_UNDEFINED)
return E_FAIL;
UINT flags = 0;
if (fmtInfo.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)
flags |= D3D11_FORMAT_SUPPORT_BUFFER;
if (fmtInfo.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)
flags |= D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER;
if (Format == DXGI_FORMAT_R16_UINT || Format == DXGI_FORMAT_R32_UINT)
flags |= D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER;
// TODO implement stream output
// D3D11_FORMAT_SUPPORT_SO_BUFFER
if (fmtInfo.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
flags |= D3D11_FORMAT_SUPPORT_TEXTURE1D
| D3D11_FORMAT_SUPPORT_TEXTURE2D
| D3D11_FORMAT_SUPPORT_TEXTURE3D
| D3D11_FORMAT_SUPPORT_TEXTURECUBE
| D3D11_FORMAT_SUPPORT_SHADER_LOAD
| D3D11_FORMAT_SUPPORT_SHADER_GATHER
| D3D11_FORMAT_SUPPORT_SHADER_GATHER_COMPARISON
| D3D11_FORMAT_SUPPORT_SHADER_SAMPLE
| D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON
| D3D11_FORMAT_SUPPORT_MIP
| D3D11_FORMAT_SUPPORT_MIP_AUTOGEN
| D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE
| D3D11_FORMAT_SUPPORT_CAST_WITHIN_BIT_LAYOUT;
}
if (fmtInfo.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
flags |= D3D11_FORMAT_SUPPORT_RENDER_TARGET;
if (fmtInfo.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT)
flags |= D3D11_FORMAT_SUPPORT_BLENDABLE;
if (fmtInfo.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
flags |= D3D11_FORMAT_SUPPORT_DEPTH_STENCIL;
if (fmtInfo.optimalTilingFeatures)
flags |= D3D11_FORMAT_SUPPORT_CPU_LOCKABLE;
if ((fmtInfo.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT)
|| (fmtInfo.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
flags |= D3D11_FORMAT_SUPPORT_TYPED_UNORDERED_ACCESS_VIEW;
// 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)
flags |= D3D11_FORMAT_SUPPORT_DISPLAY;
// Query multisampling info
VkImageFormatProperties imgInfo;
VkResult status = m_dxvkAdapter->imageFormatProperties(fmt,
VK_IMAGE_TYPE_2D,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
0, imgInfo);
if (status == VK_SUCCESS && imgInfo.sampleCounts > VK_SAMPLE_COUNT_1_BIT) {
flags |= D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET
| D3D11_FORMAT_SUPPORT_MULTISAMPLE_LOAD;
}
*pFlags = flags;
return S_OK;
}
void D3D11Device::CreateCounterBuffer() {
const uint32_t MaxCounterStructs = 1 << 16;
// The counter buffer is used as a storage buffer
DxvkBufferCreateInfo info;
info.size = MaxCounterStructs * sizeof(D3D11UavCounter);
info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
| VK_BUFFER_USAGE_TRANSFER_DST_BIT
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
| GetEnabledShaderStages();
info.access = VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_TRANSFER_WRITE_BIT
| VK_ACCESS_SHADER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT;
m_counterBuffer = m_dxvkDevice->createBuffer(
info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
// Init the counter struct allocator as well
m_counterSlices.resize(MaxCounterStructs);
for (uint32_t i = 0; i < MaxCounterStructs; i++)
m_counterSlices[i] = MaxCounterStructs - i - 1;
}
void D3D11Device::LockResourceInitContext() {
m_resourceInitMutex.lock();
}
void D3D11Device::UnlockResourceInitContext(uint64_t CommandCount) {
m_resourceInitCommands += CommandCount;
if (m_resourceInitCommands >= InitCommandThreshold)
SubmitResourceInitCommands();
m_resourceInitMutex.unlock();
}
void D3D11Device::SubmitResourceInitCommands() {
m_dxvkDevice->submitCommandList(
m_resourceInitContext->endRecording(),
nullptr, nullptr);
m_resourceInitContext->beginRecording(
m_dxvkDevice->createCommandList());
m_resourceInitCommands = 0;
}
D3D_FEATURE_LEVEL D3D11Device::GetMaxFeatureLevel() {
static const std::array<std::pair<std::string, D3D_FEATURE_LEVEL>, 6> s_featureLevels = {{
{ "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 },
}};
const std::string maxLevel = env::getEnvVar(L"DXVK_FEATURE_LEVEL");
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
: D3D_FEATURE_LEVEL_11_0;
}
2017-10-11 09:51:48 +02:00
}