2018-01-31 01:57:43 +01:00
|
|
|
#include <algorithm>
|
2017-10-11 09:51:48 +02:00
|
|
|
#include <cstring>
|
|
|
|
|
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"
|
2017-11-29 16:23:33 +01:00
|
|
|
#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"
|
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 {
|
|
|
|
|
|
|
|
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)
|
2017-11-29 16:23:33 +01:00
|
|
|
: m_dxgiDevice (dxgiDevice),
|
2017-12-04 13:39:37 +01:00
|
|
|
m_presentDevice (new D3D11PresentDevice()),
|
2017-11-29 16:23:33 +01:00
|
|
|
m_featureLevel (featureLevel),
|
|
|
|
m_featureFlags (featureFlags),
|
|
|
|
m_dxvkDevice (m_dxgiDevice->GetDXVKDevice()),
|
2018-01-07 20:05:27 +01:00
|
|
|
m_dxvkAdapter (m_dxvkDevice->adapter()),
|
|
|
|
m_dxbcOptions (m_dxvkDevice) {
|
2017-12-04 13:47:18 +01:00
|
|
|
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");
|
|
|
|
|
2017-10-11 15:32:24 +02:00
|
|
|
m_dxgiDevice->SetDeviceLayer(this);
|
2017-11-29 16:23:33 +01:00
|
|
|
m_presentDevice->SetDeviceLayer(this);
|
|
|
|
|
2018-01-20 13:22:44 +01:00
|
|
|
m_context = new D3D11ImmediateContext(this, m_dxvkDevice);
|
2018-01-13 05:00:27 +01:00
|
|
|
|
2017-12-07 18:51:41 +01:00
|
|
|
m_resourceInitContext = m_dxvkDevice->createContext();
|
2018-01-13 05:00:27 +01:00
|
|
|
m_resourceInitContext->beginRecording(
|
|
|
|
m_dxvkDevice->createCommandList());
|
2018-01-11 12:23:55 +01:00
|
|
|
|
|
|
|
CreateCounterBuffer();
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
D3D11Device::~D3D11Device() {
|
2017-11-29 16:23:33 +01:00
|
|
|
m_presentDevice->SetDeviceLayer(nullptr);
|
2017-10-11 15:32:24 +02:00
|
|
|
m_dxgiDevice->SetDeviceLayer(nullptr);
|
2017-12-11 17:01:38 +01:00
|
|
|
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);
|
|
|
|
|
2017-11-29 15:16:07 +01:00
|
|
|
if (riid == __uuidof(IDXGIDevice)
|
2017-12-09 14:46:23 +01:00
|
|
|
|| riid == __uuidof(IDXGIDevice1)
|
2017-11-29 15:16:07 +01:00
|
|
|
|| riid == __uuidof(IDXGIDevicePrivate))
|
2017-10-11 15:32:24 +02:00
|
|
|
return m_dxgiDevice->QueryInterface(riid, ppvObject);
|
|
|
|
|
2017-11-29 16:23:33 +01:00
|
|
|
if (riid == __uuidof(IDXGIPresentDevicePrivate))
|
|
|
|
return m_presentDevice->QueryInterface(riid, ppvObject);
|
|
|
|
|
2017-10-11 09:51:48 +02:00
|
|
|
Logger::warn("D3D11Device::QueryInterface: Unknown interface query");
|
2017-12-09 15:57:05 +01:00
|
|
|
Logger::warn(str::format(riid));
|
2017-10-11 09:51:48 +02:00
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
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) {
|
2017-12-07 13:17:16 +01:00
|
|
|
if (ppBuffer != nullptr) {
|
2017-12-14 15:59:55 +01:00
|
|
|
const Com<D3D11Buffer> buffer
|
|
|
|
= new D3D11Buffer(this, pDesc);
|
2017-12-07 13:31:32 +01:00
|
|
|
|
2017-12-14 15:59:55 +01:00
|
|
|
this->InitBuffer(buffer.ptr(), pInitialData);
|
|
|
|
*ppBuffer = buffer.ref();
|
2017-12-07 13:17:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
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) {
|
2017-12-23 17:05:07 +01:00
|
|
|
if (ppTexture1D != nullptr) {
|
|
|
|
const Com<D3D11Texture1D> texture
|
|
|
|
= new D3D11Texture1D(this, pDesc);
|
|
|
|
|
2018-01-05 01:15:56 +01:00
|
|
|
this->InitTexture(texture->GetTextureInfo()->image, pInitialData);
|
2017-12-23 17:05:07 +01:00
|
|
|
*ppTexture1D = texture.ref();
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
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) {
|
2017-12-08 23:13:15 +01:00
|
|
|
if (ppTexture2D != nullptr) {
|
2017-12-19 16:01:50 +01:00
|
|
|
const Com<D3D11Texture2D> texture
|
|
|
|
= new D3D11Texture2D(this, pDesc);
|
2017-12-08 23:13:15 +01:00
|
|
|
|
2018-01-05 01:15:56 +01:00
|
|
|
this->InitTexture(texture->GetTextureInfo()->image, pInitialData);
|
2017-12-19 16:01:50 +01:00
|
|
|
*ppTexture2D = texture.ref();
|
2017-12-08 23:13:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
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) {
|
2017-12-23 17:05:07 +01:00
|
|
|
if (ppTexture3D != nullptr) {
|
|
|
|
const Com<D3D11Texture3D> texture
|
|
|
|
= new D3D11Texture3D(this, pDesc);
|
|
|
|
|
2018-01-05 01:15:56 +01:00
|
|
|
this->InitTexture(texture->GetTextureInfo()->image, pInitialData);
|
2017-12-23 17:05:07 +01:00
|
|
|
*ppTexture3D = texture.ref();
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
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) {
|
2017-12-09 14:46:23 +01:00
|
|
|
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
|
|
|
|
pResource->GetType(&resourceDim);
|
2017-12-09 15:57:05 +01: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) {
|
|
|
|
if (FAILED(GetShaderResourceViewDescFromResource(pResource, &desc)))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
} else {
|
|
|
|
desc = *pDesc;
|
2018-01-17 15:19:55 +01:00
|
|
|
|
|
|
|
if (FAILED(SetShaderResourceViewDescUnspecValues(pResource, &desc)))
|
|
|
|
return E_INVALIDARG;
|
2017-12-09 19:06:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
|
2017-12-27 14:32:07 +01:00
|
|
|
auto resource = static_cast<D3D11Buffer*>(pResource);
|
|
|
|
|
2017-12-28 16:33:42 +01:00
|
|
|
D3D11_BUFFER_DESC resourceDesc;
|
|
|
|
resource->GetDesc(&resourceDesc);
|
2017-12-27 14:32:07 +01:00
|
|
|
|
2018-02-22 21:38:45 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-12-28 16:33:42 +01:00
|
|
|
DxvkBufferViewCreateInfo viewInfo;
|
2017-12-27 14:32:07 +01:00
|
|
|
|
2017-12-29 12:11:45 +01:00
|
|
|
D3D11_BUFFEREX_SRV bufInfo;
|
|
|
|
|
2017-12-28 16:33:42 +01:00
|
|
|
if (desc.ViewDimension == D3D11_SRV_DIMENSION_BUFFEREX) {
|
2017-12-29 12:11:45 +01:00
|
|
|
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.
|
2017-12-28 16:33:42 +01:00
|
|
|
viewInfo.format = VK_FORMAT_R32_UINT;
|
2017-12-29 12:11:45 +01:00
|
|
|
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;
|
2017-12-28 16:33:42 +01:00
|
|
|
} 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);
|
2017-12-29 12:11:45 +01:00
|
|
|
viewInfo.rangeOffset = formatInfo->elementSize * bufInfo.FirstElement;
|
|
|
|
viewInfo.rangeLength = formatInfo->elementSize * bufInfo.NumElements;
|
2017-12-28 16:33:42 +01:00
|
|
|
|
|
|
|
if (formatInfo->flags.test(DxvkFormatFlag::BlockCompressed)) {
|
|
|
|
Logger::err("D3D11Device: Compressed formats for buffer views not supported");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
2017-12-27 14:32:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2017-12-09 19:06:51 +01:00
|
|
|
} else {
|
2017-12-19 16:01:50 +01:00
|
|
|
// Retrieve info about the image
|
2018-01-05 01:15:56 +01:00
|
|
|
const D3D11TextureInfo* textureInfo
|
|
|
|
= GetCommonTextureInfo(pResource);
|
2017-12-19 14:47:35 +01:00
|
|
|
|
2018-02-22 21:38:45 +01:00
|
|
|
if ((textureInfo->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
|
2018-01-05 01:15:56 +01:00
|
|
|
->LookupFormat(desc.Format, textureInfo->formatMode);
|
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;
|
2017-12-09 19:06:51 +01:00
|
|
|
|
|
|
|
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;
|
2017-12-09 19:06:51 +01:00
|
|
|
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;
|
2017-12-09 19:06:51 +01:00
|
|
|
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;
|
2017-12-09 19:06:51 +01:00
|
|
|
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;
|
2017-12-09 19:06:51 +01:00
|
|
|
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;
|
2017-12-09 19:06:51 +01:00
|
|
|
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;
|
2017-12-09 19:06:51 +01:00
|
|
|
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;
|
2017-12-09 19:06:51 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_SRV_DIMENSION_TEXTURECUBE:
|
2018-01-11 12:33:38 +01:00
|
|
|
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;
|
2017-12-09 19:06:51 +01:00
|
|
|
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;
|
2017-12-09 19:06:51 +01:00
|
|
|
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)
|
2017-12-27 14:32:07 +01:00
|
|
|
return S_FALSE;
|
2017-12-09 19:06:51 +01:00
|
|
|
|
|
|
|
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(
|
2018-01-05 01:15:56 +01:00
|
|
|
textureInfo->image, viewInfo)));
|
2017-12-09 19:06:51 +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::CreateUnorderedAccessView(
|
2017-10-11 09:51:48 +02:00
|
|
|
ID3D11Resource* pResource,
|
|
|
|
const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
|
|
|
|
ID3D11UnorderedAccessView** ppUAView) {
|
2017-12-28 19:05:53 +01:00
|
|
|
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(GetUnorderedAccessViewDescFromResource(pResource, &desc)))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
} else {
|
|
|
|
desc = *pDesc;
|
2018-01-28 11:30:15 +01:00
|
|
|
|
|
|
|
if (FAILED(SetUnorderedAccessViewDescUnspecValues(pResource, &desc)))
|
|
|
|
return E_INVALIDARG;
|
2017-12-28 19:05:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
|
|
|
|
auto resource = static_cast<D3D11Buffer*>(pResource);
|
|
|
|
|
|
|
|
D3D11_BUFFER_DESC resourceDesc;
|
|
|
|
resource->GetDesc(&resourceDesc);
|
|
|
|
|
2018-02-22 21:38:45 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-12-28 19:05:53 +01:00
|
|
|
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 {
|
2018-01-11 12:23:55 +01:00
|
|
|
// 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();
|
|
|
|
|
2017-12-28 19:05:53 +01:00
|
|
|
*ppUAView = ref(new D3D11UnorderedAccessView(
|
|
|
|
this, pResource, desc,
|
|
|
|
m_dxvkDevice->createBufferView(
|
2018-01-11 12:23:55 +01:00
|
|
|
resource->GetBufferSlice().buffer(), viewInfo),
|
|
|
|
counterSlice));
|
2017-12-28 19:05:53 +01:00
|
|
|
return S_OK;
|
|
|
|
} catch (const DxvkError& e) {
|
|
|
|
Logger::err(e.message());
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
} else {
|
2018-01-01 19:46:19 +01:00
|
|
|
// Retrieve info about the image
|
2018-01-05 01:15:56 +01:00
|
|
|
const D3D11TextureInfo* textureInfo
|
|
|
|
= GetCommonTextureInfo(pResource);
|
2018-01-01 19:46:19 +01:00
|
|
|
|
2018-02-22 21:38:45 +01:00
|
|
|
if ((textureInfo->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
|
2018-01-05 01:15:56 +01:00
|
|
|
->LookupFormat(desc.Format, textureInfo->formatMode);
|
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:
|
2018-01-28 11:30:15 +01:00
|
|
|
// 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(
|
2018-01-06 02:09:07 +01:00
|
|
|
"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(
|
2018-01-11 12:23:55 +01:00
|
|
|
textureInfo->image, 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-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) {
|
2017-12-09 14:46:23 +01:00
|
|
|
// Only 2D textures and 2D texture arrays are allowed
|
2017-11-29 15:16:07 +01:00
|
|
|
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
|
|
|
|
pResource->GetType(&resourceDim);
|
|
|
|
|
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) {
|
|
|
|
if (FAILED(GetRenderTargetViewDescFromResource(pResource, &desc)))
|
|
|
|
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
|
|
|
|
|
|
|
if (FAILED(SetRenderTargetViewDescUnspecValues(pResource, &desc)))
|
|
|
|
return E_INVALIDARG;
|
2017-11-29 20:19:40 +01:00
|
|
|
}
|
|
|
|
|
2017-12-09 19:36:38 +01:00
|
|
|
// Retrieve the image that we are going to create the view for
|
2018-01-05 01:15:56 +01:00
|
|
|
const D3D11TextureInfo* textureInfo
|
|
|
|
= GetCommonTextureInfo(pResource);
|
2017-12-09 19:36:38 +01:00
|
|
|
|
2018-02-22 21:38:45 +01:00
|
|
|
if ((textureInfo->bindFlags & D3D11_BIND_RENDER_TARGET) == 0) {
|
|
|
|
Logger::warn("D3D11: Trying to create RTV for texture without D3D11_BIND_RENDER_TARGET");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2017-11-29 20:19:40 +01:00
|
|
|
// 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;
|
2017-11-29 15:16:07 +01:00
|
|
|
|
2017-11-29 20:19:40 +01:00
|
|
|
switch (desc.ViewDimension) {
|
2018-02-26 15:21:18 +01:00
|
|
|
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;
|
|
|
|
|
2017-11-29 20:19:40 +01:00
|
|
|
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;
|
2017-12-19 18:12:18 +01:00
|
|
|
viewInfo.minLayer = desc.Texture2DMSArray.FirstArraySlice;
|
|
|
|
viewInfo.numLayers = desc.Texture2DMSArray.ArraySize;
|
2017-11-29 20:19:40 +01:00
|
|
|
break;
|
|
|
|
|
2018-02-14 03:16:53 +01:00
|
|
|
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;
|
|
|
|
|
2017-11-29 20:19:40 +01:00
|
|
|
default:
|
|
|
|
Logger::err(str::format(
|
2017-12-08 23:25:38 +01:00
|
|
|
"D3D11: pDesc->ViewDimension not supported for render target views: ",
|
2017-11-29 20:19:40 +01:00
|
|
|
desc.ViewDimension));
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the actual image view if requested
|
|
|
|
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 {
|
2017-12-09 02:09:13 +01:00
|
|
|
*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(
|
2018-01-05 01:15:56 +01:00
|
|
|
textureInfo->image, viewInfo)));
|
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) {
|
2017-12-09 14:46:23 +01:00
|
|
|
// Only 2D textures and 2D texture arrays are allowed
|
2017-12-08 23:25:38 +01:00
|
|
|
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(GetDepthStencilViewDescFromResource(pResource, &desc)))
|
|
|
|
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
|
|
|
|
|
|
|
if (FAILED(SetDepthStencilViewDescUnspecValues(pResource, &desc)))
|
|
|
|
return E_INVALIDARG;
|
2017-12-08 23:25:38 +01:00
|
|
|
}
|
|
|
|
|
2017-12-09 19:36:38 +01:00
|
|
|
// Retrieve the image that we are going to create the view for
|
2018-01-05 01:15:56 +01:00
|
|
|
const D3D11TextureInfo* textureInfo
|
|
|
|
= GetCommonTextureInfo(pResource);
|
2017-12-09 19:36:38 +01:00
|
|
|
|
2018-02-22 21:38:45 +01:00
|
|
|
if ((textureInfo->bindFlags & D3D11_BIND_DEPTH_STENCIL) == 0) {
|
|
|
|
Logger::warn("D3D11: Trying to create DSV for texture without D3D11_BIND_DEPTH_STENCIL");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2017-12-08 23:25:38 +01:00
|
|
|
// 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;
|
2017-12-08 23:25:38 +01:00
|
|
|
|
|
|
|
switch (desc.ViewDimension) {
|
2018-02-26 15:21:18 +01:00
|
|
|
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;
|
|
|
|
|
2017-12-08 23:25:38 +01:00
|
|
|
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;
|
2017-12-19 18:12:18 +01:00
|
|
|
viewInfo.minLayer = desc.Texture2DMSArray.FirstArraySlice;
|
|
|
|
viewInfo.numLayers = desc.Texture2DMSArray.ArraySize;
|
2017-12-08 23:25:38 +01:00
|
|
|
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)
|
2017-12-27 14:32:07 +01:00
|
|
|
return S_FALSE;
|
2017-12-08 23:25:38 +01:00
|
|
|
|
|
|
|
try {
|
2017-12-09 02:09:13 +01:00
|
|
|
*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(
|
2018-01-05 01:15:56 +01:00
|
|
|
textureInfo->image, viewInfo)));
|
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) {
|
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();
|
2017-12-07 12:45:02 +01:00
|
|
|
|
2017-12-08 00:44:58 +01:00
|
|
|
std::vector<DxvkVertexAttribute> attributes;
|
|
|
|
std::vector<DxvkVertexBinding> bindings;
|
2017-12-07 12:45:02 +01:00
|
|
|
|
|
|
|
for (uint32_t i = 0; i < NumElements; i++) {
|
|
|
|
const DxbcSgnEntry* entry = inputSignature->find(
|
|
|
|
pInputElementDescs[i].SemanticName,
|
|
|
|
pInputElementDescs[i].SemanticIndex);
|
|
|
|
|
|
|
|
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));
|
2017-12-30 19:11:20 +01:00
|
|
|
continue;
|
2017-12-07 12:45:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create vertex input attribute description
|
2017-12-08 00:44:58 +01:00
|
|
|
DxvkVertexAttribute attrib;
|
2017-12-07 12:45:02 +01:00
|
|
|
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;
|
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++) {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2017-12-07 12:45:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
attributes.push_back(attrib);
|
|
|
|
|
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
|
|
|
|
? 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;
|
|
|
|
|
|
|
|
for (const auto& existingBinding : bindings) {
|
|
|
|
if (binding.binding == existingBinding.binding) {
|
|
|
|
bindingDefined = true;
|
|
|
|
|
|
|
|
if (binding.inputRate != existingBinding.inputRate) {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bindingDefined)
|
|
|
|
bindings.push_back(binding);
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
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"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-23 12:55:23 +01:00
|
|
|
std::sort(bindings.begin(), bindings.end(),
|
|
|
|
[] (const DxvkVertexBinding& a, const DxvkVertexBinding& b) {
|
|
|
|
return a.binding < b.binding;
|
|
|
|
});
|
|
|
|
|
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,
|
2017-12-08 00:44:58 +01:00
|
|
|
attributes.size(),
|
|
|
|
attributes.data(),
|
|
|
|
bindings.size(),
|
|
|
|
bindings.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) {
|
2017-12-06 18:54:01 +01:00
|
|
|
D3D11ShaderModule module;
|
|
|
|
|
|
|
|
if (FAILED(this->CreateShaderModule(&module,
|
|
|
|
pShaderBytecode, BytecodeLength, pClassLinkage)))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
if (ppVertexShader != nullptr) {
|
|
|
|
*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) {
|
|
|
|
*ppGeometryShader = ref(new D3D11GeometryShader(
|
|
|
|
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::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) {
|
2017-12-06 18:54:01 +01:00
|
|
|
D3D11ShaderModule module;
|
|
|
|
|
|
|
|
if (FAILED(this->CreateShaderModule(&module,
|
|
|
|
pShaderBytecode, BytecodeLength, pClassLinkage)))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
if (ppPixelShader != nullptr) {
|
|
|
|
*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) {
|
2018-01-29 11:53:57 +01:00
|
|
|
D3D11ShaderModule module;
|
2018-02-26 14:23:41 +01:00
|
|
|
*ppHullShader = nullptr;
|
2018-01-29 11:53:57 +01:00
|
|
|
|
|
|
|
if (FAILED(this->CreateShaderModule(&module,
|
|
|
|
pShaderBytecode, BytecodeLength, pClassLinkage)))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
if (ppHullShader != nullptr) {
|
|
|
|
*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) {
|
2018-01-29 11:53:57 +01:00
|
|
|
D3D11ShaderModule module;
|
2018-02-26 14:23:41 +01:00
|
|
|
*ppDomainShader = nullptr;
|
2018-01-29 11:53:57 +01:00
|
|
|
if (FAILED(this->CreateShaderModule(&module,
|
|
|
|
pShaderBytecode, BytecodeLength, pClassLinkage)))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
if (ppDomainShader != nullptr) {
|
|
|
|
*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) {
|
|
|
|
*ppComputeShader = ref(new D3D11ComputeShader(
|
|
|
|
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::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) {
|
2017-12-11 13:03:07 +01:00
|
|
|
D3D11_BLEND_DESC desc;
|
|
|
|
|
|
|
|
if (pBlendStateDesc != nullptr) {
|
|
|
|
desc = *pBlendStateDesc;
|
|
|
|
} else {
|
|
|
|
desc.AlphaToCoverageEnable = FALSE;
|
|
|
|
desc.IndependentBlendEnable = FALSE;
|
|
|
|
|
|
|
|
// 1-7 must be ignored if IndependentBlendEnable is disabled so
|
|
|
|
// technically this is not needed, but since this structure is
|
|
|
|
// going to be copied around we'll initialize it nonetheless
|
|
|
|
for (uint32_t i = 0; i < 8; i++) {
|
|
|
|
desc.RenderTarget[i].BlendEnable = FALSE;
|
|
|
|
desc.RenderTarget[i].SrcBlend = D3D11_BLEND_ONE;
|
|
|
|
desc.RenderTarget[i].DestBlend = D3D11_BLEND_ZERO;
|
|
|
|
desc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD;
|
|
|
|
desc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE;
|
|
|
|
desc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO;
|
|
|
|
desc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
|
|
|
desc.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
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) {
|
2017-12-11 01:43:15 +01:00
|
|
|
D3D11_DEPTH_STENCIL_DESC desc;
|
|
|
|
|
|
|
|
if (pDepthStencilDesc != nullptr) {
|
|
|
|
desc = *pDepthStencilDesc;
|
|
|
|
} else {
|
|
|
|
D3D11_DEPTH_STENCILOP_DESC stencilOp;
|
|
|
|
stencilOp.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
|
|
|
stencilOp.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
|
|
|
|
stencilOp.StencilPassOp = D3D11_STENCIL_OP_KEEP;
|
|
|
|
stencilOp.StencilFailOp = D3D11_STENCIL_OP_KEEP;
|
|
|
|
|
|
|
|
desc.DepthEnable = TRUE;
|
|
|
|
desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
|
|
|
desc.DepthFunc = D3D11_COMPARISON_LESS;
|
|
|
|
desc.StencilEnable = FALSE;
|
|
|
|
desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
|
|
|
|
desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
|
|
|
|
desc.FrontFace = stencilOp;
|
|
|
|
desc.BackFace = stencilOp;
|
|
|
|
}
|
|
|
|
|
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) {
|
2017-12-06 13:16:54 +01:00
|
|
|
D3D11_RASTERIZER_DESC desc;
|
|
|
|
|
|
|
|
if (pRasterizerDesc != nullptr) {
|
|
|
|
desc = *pRasterizerDesc;
|
|
|
|
} else {
|
|
|
|
desc.FillMode = D3D11_FILL_SOLID;
|
|
|
|
desc.CullMode = D3D11_CULL_BACK;
|
|
|
|
desc.FrontCounterClockwise = FALSE;
|
|
|
|
desc.DepthBias = 0;
|
|
|
|
desc.SlopeScaledDepthBias = 0.0f;
|
|
|
|
desc.DepthBiasClamp = 0.0f;
|
|
|
|
desc.DepthClipEnable = TRUE;
|
|
|
|
desc.ScissorEnable = FALSE;
|
|
|
|
desc.MultisampleEnable = FALSE;
|
|
|
|
desc.AntialiasedLineEnable = FALSE;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
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) {
|
2017-12-09 20:49:56 +01:00
|
|
|
DxvkSamplerCreateInfo info;
|
|
|
|
|
|
|
|
// While D3D11_FILTER is technically an enum, its value bits
|
|
|
|
// can be used to decode the filter properties more efficiently.
|
|
|
|
const uint32_t filterBits = static_cast<uint32_t>(pSamplerDesc->Filter);
|
|
|
|
|
|
|
|
info.magFilter = (filterBits & 0x04) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
|
|
|
|
info.minFilter = (filterBits & 0x10) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
|
|
|
|
info.mipmapMode = (filterBits & 0x01) ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
|
|
|
info.useAnisotropy = (filterBits & 0x40) ? VK_TRUE : VK_FALSE;
|
|
|
|
info.compareToDepth = (filterBits & 0x80) ? VK_TRUE : VK_FALSE;
|
|
|
|
|
|
|
|
// Check for any unknown flags
|
|
|
|
if (filterBits & 0xFFFFFF2A) {
|
|
|
|
Logger::err(str::format("D3D11: Unsupported filter bits: ", filterBits));
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set up the remaining properties, which are
|
|
|
|
// stored directly in the sampler description
|
|
|
|
info.mipmapLodBias = pSamplerDesc->MipLODBias;
|
|
|
|
info.mipmapLodMin = pSamplerDesc->MinLOD;
|
|
|
|
info.mipmapLodMax = pSamplerDesc->MaxLOD;
|
|
|
|
info.maxAnisotropy = pSamplerDesc->MaxAnisotropy;
|
|
|
|
info.addressModeU = DecodeAddressMode(pSamplerDesc->AddressU);
|
|
|
|
info.addressModeV = DecodeAddressMode(pSamplerDesc->AddressV);
|
|
|
|
info.addressModeW = DecodeAddressMode(pSamplerDesc->AddressW);
|
|
|
|
info.compareOp = DecodeCompareOp(pSamplerDesc->ComparisonFunc);
|
|
|
|
info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
2017-12-21 16:54:20 +01:00
|
|
|
info.usePixelCoord = VK_FALSE; // Not supported in D3D11
|
2017-12-09 20:49:56 +01:00
|
|
|
|
2017-12-21 16:54:20 +01:00
|
|
|
// Try to find a matching border color if clamp to border is enabled
|
2017-12-09 20:49:56 +01:00
|
|
|
if (info.addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER
|
|
|
|
|| info.addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER
|
|
|
|
|| info.addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)
|
2017-12-21 16:54:20 +01:00
|
|
|
info.borderColor = DecodeBorderColor(pSamplerDesc->BorderColor);
|
2017-12-09 20:49:56 +01:00
|
|
|
|
|
|
|
// Create sampler object if the application requests it
|
|
|
|
if (ppSamplerState == nullptr)
|
2017-12-27 14:32:07 +01:00
|
|
|
return S_FALSE;
|
2017-12-09 20:49:56 +01:00
|
|
|
|
|
|
|
try {
|
|
|
|
*ppSamplerState = ref(new D3D11SamplerState(this,
|
|
|
|
*pSamplerDesc, m_dxvkDevice->createSampler(info)));
|
|
|
|
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-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 {
|
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-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) {
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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) {
|
2017-12-19 11:05:41 +01:00
|
|
|
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) {
|
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.
|
2017-12-09 14:46:23 +01:00
|
|
|
*pNumQualityLevels = 0;
|
|
|
|
|
2017-12-09 19:44:06 +01:00
|
|
|
// We need to check whether the format is
|
2017-12-19 14:47:35 +01:00
|
|
|
VkFormat format = m_dxgiAdapter->LookupFormat(
|
2017-12-20 14:54:24 +01:00
|
|
|
Format, DxgiFormatMode::Any).format;
|
2017-12-09 14:46:23 +01:00
|
|
|
|
|
|
|
if (format == VK_FORMAT_UNDEFINED) {
|
|
|
|
Logger::err(str::format("D3D11: Unsupported format: ", Format));
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2017-12-09 19:44:06 +01:00
|
|
|
// D3D may legally query non-power-of-two sample counts as well
|
2017-12-09 14:46:23 +01:00
|
|
|
VkSampleCountFlagBits sampleCountFlag = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
|
|
|
|
if (FAILED(GetSampleCount(SampleCount, &sampleCountFlag)))
|
2017-12-09 19:44:06 +01:00
|
|
|
return S_OK;
|
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) {
|
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) {
|
2017-12-19 11:05:41 +01:00
|
|
|
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;
|
|
|
|
|
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;
|
|
|
|
|
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));
|
|
|
|
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) {
|
2017-10-11 15:32:24 +02:00
|
|
|
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) {
|
2017-10-11 15:32:24 +02:00
|
|
|
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) {
|
2017-10-11 15:32:24 +02:00
|
|
|
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() {
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-11 12:23:55 +01:00
|
|
|
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() {
|
2018-01-13 23:40:17 +01:00
|
|
|
LockResourceInitContext();
|
|
|
|
if (m_resourceInitCommands != 0)
|
|
|
|
SubmitResourceInitCommands();
|
|
|
|
UnlockResourceInitContext(0);
|
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;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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) {
|
2017-12-02 16:47:06 +01:00
|
|
|
// We currently only support 11_0 interfaces
|
2018-01-30 12:19:53 +01:00
|
|
|
if (featureLevel > GetMaxFeatureLevel())
|
2017-12-02 16:47:06 +01:00
|
|
|
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();
|
2018-01-28 19:37:22 +01:00
|
|
|
VkPhysicalDeviceFeatures enabled = {};
|
2017-12-02 16:47:06 +01:00
|
|
|
|
|
|
|
if (featureLevel >= D3D_FEATURE_LEVEL_9_1) {
|
2018-01-01 17:14:06 +01:00
|
|
|
enabled.depthClamp = VK_TRUE;
|
|
|
|
enabled.depthBiasClamp = VK_TRUE;
|
|
|
|
enabled.fillModeNonSolid = VK_TRUE;
|
|
|
|
enabled.pipelineStatisticsQuery = supported.pipelineStatisticsQuery;
|
2018-02-08 10:06:10 +01:00
|
|
|
enabled.sampleRateShading = VK_TRUE;
|
2018-01-01 17:14:06 +01:00
|
|
|
enabled.samplerAnisotropy = VK_TRUE;
|
|
|
|
enabled.shaderClipDistance = VK_TRUE;
|
|
|
|
enabled.shaderCullDistance = VK_TRUE;
|
2018-01-09 00:51:10 +01:00
|
|
|
enabled.robustBufferAccess = VK_TRUE;
|
2017-12-02 16:47:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (featureLevel >= D3D_FEATURE_LEVEL_9_2) {
|
2018-01-01 17:14:06 +01:00
|
|
|
enabled.occlusionQueryPrecise = VK_TRUE;
|
2017-12-02 16:47:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (featureLevel >= D3D_FEATURE_LEVEL_9_3) {
|
2018-01-01 17:14:06 +01:00
|
|
|
enabled.multiViewport = VK_TRUE;
|
|
|
|
enabled.independentBlend = VK_TRUE;
|
2017-12-02 16:47:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (featureLevel >= D3D_FEATURE_LEVEL_10_0) {
|
2018-01-01 17:14:06 +01:00
|
|
|
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;
|
2017-12-02 16:47:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (featureLevel >= D3D_FEATURE_LEVEL_10_1) {
|
2018-01-18 08:42:57 +01:00
|
|
|
enabled.dualSrcBlend = VK_TRUE;
|
2018-01-01 17:14:06 +01:00
|
|
|
enabled.imageCubeArray = VK_TRUE;
|
2017-12-02 16:47:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (featureLevel >= D3D_FEATURE_LEVEL_11_0) {
|
2018-01-01 17:14:06 +01:00
|
|
|
enabled.shaderFloat64 = supported.shaderFloat64;
|
|
|
|
enabled.shaderInt64 = supported.shaderInt64;
|
|
|
|
enabled.tessellationShader = VK_TRUE;
|
|
|
|
enabled.shaderStorageImageReadWithoutFormat = VK_TRUE;
|
|
|
|
enabled.shaderStorageImageWriteWithoutFormat = 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
|
|
|
|
|
|
|
HRESULT D3D11Device::CreateShaderModule(
|
|
|
|
D3D11ShaderModule* pShaderModule,
|
|
|
|
const void* pShaderBytecode,
|
|
|
|
size_t BytecodeLength,
|
|
|
|
ID3D11ClassLinkage* pClassLinkage) {
|
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 {
|
|
|
|
*pShaderModule = D3D11ShaderModule(
|
2018-01-07 20:05:27 +01:00
|
|
|
&m_dxbcOptions, this, 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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-07 13:17:16 +01:00
|
|
|
|
2017-12-07 18:51:41 +01:00
|
|
|
void D3D11Device::InitBuffer(
|
2017-12-14 15:59:55 +01:00
|
|
|
D3D11Buffer* pBuffer,
|
2017-12-07 18:51:41 +01:00
|
|
|
const D3D11_SUBRESOURCE_DATA* pInitialData) {
|
2017-12-14 19:07:08 +01:00
|
|
|
const DxvkBufferSlice bufferSlice
|
2017-12-15 19:11:10 +01:00
|
|
|
= pBuffer->GetBufferSlice();
|
2017-12-07 18:51:41 +01:00
|
|
|
|
|
|
|
if (pInitialData != nullptr) {
|
2018-01-13 23:40:17 +01:00
|
|
|
LockResourceInitContext();
|
2018-01-13 05:00:27 +01:00
|
|
|
|
2017-12-07 18:51:41 +01:00
|
|
|
m_resourceInitContext->updateBuffer(
|
2017-12-14 19:07:08 +01:00
|
|
|
bufferSlice.buffer(),
|
2017-12-14 19:09:49 +01:00
|
|
|
bufferSlice.offset(),
|
|
|
|
bufferSlice.length(),
|
2017-12-07 18:51:41 +01:00
|
|
|
pInitialData->pSysMem);
|
2018-01-13 23:40:17 +01:00
|
|
|
|
|
|
|
UnlockResourceInitContext(1);
|
2017-12-07 18:51:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-08 23:13:15 +01:00
|
|
|
void D3D11Device::InitTexture(
|
2017-12-23 17:05:07 +01:00
|
|
|
const Rc<DxvkImage>& image,
|
2017-12-08 23:13:15 +01:00
|
|
|
const D3D11_SUBRESOURCE_DATA* pInitialData) {
|
2017-12-10 19:10:17 +01:00
|
|
|
const DxvkFormatInfo* formatInfo = imageFormatInfo(image->info().format);
|
2017-12-08 23:13:15 +01:00
|
|
|
|
2017-12-10 15:57:51 +01:00
|
|
|
if (pInitialData != nullptr) {
|
2018-01-13 23:40:17 +01:00
|
|
|
LockResourceInitContext();
|
|
|
|
|
2017-12-10 19:10:17 +01:00
|
|
|
// pInitialData is an array that stores an entry for
|
|
|
|
// every single subresource. Since we will define all
|
|
|
|
// subresources, this counts as initialization.
|
2017-12-10 15:57:51 +01:00
|
|
|
VkImageSubresourceLayers subresourceLayers;
|
2017-12-10 19:10:17 +01:00
|
|
|
subresourceLayers.aspectMask = formatInfo->aspectMask;
|
2017-12-10 15:57:51 +01:00
|
|
|
subresourceLayers.mipLevel = 0;
|
|
|
|
subresourceLayers.baseArrayLayer = 0;
|
2017-12-10 19:10:17 +01:00
|
|
|
subresourceLayers.layerCount = 1;
|
2017-12-10 15:57:51 +01:00
|
|
|
|
2017-12-10 19:10:17 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2018-01-13 23:40:17 +01:00
|
|
|
|
|
|
|
const uint32_t subresourceCount =
|
|
|
|
image->info().numLayers * image->info().mipLevels;
|
|
|
|
UnlockResourceInitContext(subresourceCount);
|
2017-12-10 19:10:17 +01:00
|
|
|
} else {
|
2018-01-13 23:40:17 +01:00
|
|
|
LockResourceInitContext();
|
|
|
|
|
2018-01-19 18:11:20 +01:00
|
|
|
// 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.
|
2017-12-10 19:10:17 +01:00
|
|
|
VkImageSubresourceRange subresources;
|
|
|
|
subresources.aspectMask = formatInfo->aspectMask;
|
|
|
|
subresources.baseMipLevel = 0;
|
|
|
|
subresources.levelCount = image->info().mipLevels;
|
|
|
|
subresources.baseArrayLayer = 0;
|
|
|
|
subresources.layerCount = image->info().numLayers;
|
2018-01-02 21:32:39 +01:00
|
|
|
|
2018-01-19 18:11:20 +01:00
|
|
|
const DxvkFormatInfo* formatInfo = imageFormatInfo(image->info().format);
|
|
|
|
|
|
|
|
if (formatInfo->flags.test(DxvkFormatFlag::BlockCompressed)) {
|
|
|
|
m_resourceInitContext->initImage(
|
|
|
|
image, subresources);
|
2018-01-02 21:32:39 +01:00
|
|
|
} else {
|
2018-01-19 18:11:20 +01:00
|
|
|
if (subresources.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
|
|
|
|
m_resourceInitContext->clearColorImage(
|
2018-01-28 19:37:22 +01:00
|
|
|
image, VkClearColorValue(), subresources);
|
2018-01-19 18:11:20 +01:00
|
|
|
} else {
|
|
|
|
VkClearDepthStencilValue value;
|
|
|
|
value.depth = 1.0f;
|
|
|
|
value.stencil = 0;
|
|
|
|
|
|
|
|
m_resourceInitContext->clearDepthStencilImage(
|
|
|
|
image, value, subresources);
|
|
|
|
}
|
2018-01-02 21:32:39 +01:00
|
|
|
}
|
2018-01-13 23:40:17 +01:00
|
|
|
|
|
|
|
UnlockResourceInitContext(1);
|
2017-12-10 15:57:51 +01:00
|
|
|
}
|
2017-12-08 23:13:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-09 19:06:51 +01:00
|
|
|
HRESULT D3D11Device::GetShaderResourceViewDescFromResource(
|
|
|
|
ID3D11Resource* pResource,
|
|
|
|
D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc) {
|
|
|
|
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
|
|
|
|
pResource->GetType(&resourceDim);
|
|
|
|
|
|
|
|
switch (resourceDim) {
|
2018-01-17 15:19:55 +01:00
|
|
|
case D3D11_RESOURCE_DIMENSION_BUFFER: {
|
|
|
|
D3D11_BUFFER_DESC bufferDesc;
|
|
|
|
static_cast<D3D11Buffer*>(pResource)->GetDesc(&bufferDesc);
|
|
|
|
|
|
|
|
if (bufferDesc.MiscFlags == D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) {
|
|
|
|
pDesc->Format = DXGI_FORMAT_UNKNOWN;
|
|
|
|
pDesc->ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
|
|
|
pDesc->Buffer.FirstElement = 0;
|
|
|
|
pDesc->Buffer.NumElements = bufferDesc.ByteWidth / bufferDesc.StructureByteStride;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
} return E_INVALIDARG;
|
|
|
|
|
2017-12-24 13:33:22 +01:00
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
|
|
|
|
D3D11_TEXTURE1D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
pDesc->Format = resourceDesc.Format;
|
|
|
|
|
|
|
|
if (resourceDesc.ArraySize == 1) {
|
|
|
|
pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
|
|
|
|
pDesc->Texture1D.MostDetailedMip = 0;
|
|
|
|
pDesc->Texture1D.MipLevels = resourceDesc.MipLevels;
|
|
|
|
} else {
|
|
|
|
pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
|
|
|
|
pDesc->Texture1DArray.MostDetailedMip = 0;
|
|
|
|
pDesc->Texture1DArray.MipLevels = resourceDesc.MipLevels;
|
|
|
|
pDesc->Texture1DArray.FirstArraySlice = 0;
|
|
|
|
pDesc->Texture1DArray.ArraySize = resourceDesc.ArraySize;
|
|
|
|
}
|
|
|
|
} return S_OK;
|
2017-12-09 19:06:51 +01:00
|
|
|
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
|
|
|
|
D3D11_TEXTURE2D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
pDesc->Format = resourceDesc.Format;
|
|
|
|
|
|
|
|
if (resourceDesc.SampleDesc.Count == 1) {
|
|
|
|
if (resourceDesc.ArraySize == 1) {
|
|
|
|
pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
|
|
|
pDesc->Texture2D.MostDetailedMip = 0;
|
|
|
|
pDesc->Texture2D.MipLevels = resourceDesc.MipLevels;
|
|
|
|
} else {
|
|
|
|
pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
|
|
|
|
pDesc->Texture2DArray.MostDetailedMip = 0;
|
|
|
|
pDesc->Texture2DArray.MipLevels = resourceDesc.MipLevels;
|
|
|
|
pDesc->Texture2DArray.FirstArraySlice = 0;
|
|
|
|
pDesc->Texture2DArray.ArraySize = resourceDesc.ArraySize;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (resourceDesc.ArraySize == 1) {
|
|
|
|
pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
|
|
|
|
} else {
|
|
|
|
pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
|
|
|
|
pDesc->Texture2DMSArray.FirstArraySlice = 0;
|
|
|
|
pDesc->Texture2DMSArray.ArraySize = resourceDesc.ArraySize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} return S_OK;
|
|
|
|
|
2017-12-24 13:33:22 +01:00
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE3D: {
|
|
|
|
D3D11_TEXTURE3D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture3D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
pDesc->Format = resourceDesc.Format;
|
2017-12-24 15:29:10 +01:00
|
|
|
pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
|
2017-12-24 13:33:22 +01:00
|
|
|
pDesc->Texture3D.MostDetailedMip = 0;
|
|
|
|
pDesc->Texture3D.MipLevels = resourceDesc.MipLevels;
|
|
|
|
} return S_OK;
|
|
|
|
|
2017-12-09 19:06:51 +01:00
|
|
|
default:
|
|
|
|
Logger::err(str::format(
|
|
|
|
"D3D11: Unsupported dimension for shader resource view: ",
|
|
|
|
resourceDim));
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT D3D11Device::GetUnorderedAccessViewDescFromResource(
|
|
|
|
ID3D11Resource* pResource,
|
|
|
|
D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc) {
|
2018-01-28 10:57:16 +01:00
|
|
|
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
|
|
|
|
pResource->GetType(&resourceDim);
|
|
|
|
|
|
|
|
switch (resourceDim) {
|
|
|
|
case D3D11_RESOURCE_DIMENSION_BUFFER: {
|
|
|
|
D3D11_BUFFER_DESC bufferDesc;
|
|
|
|
static_cast<D3D11Buffer*>(pResource)->GetDesc(&bufferDesc);
|
|
|
|
|
|
|
|
if (bufferDesc.MiscFlags == D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) {
|
|
|
|
pDesc->Format = DXGI_FORMAT_UNKNOWN;
|
|
|
|
pDesc->ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
|
|
|
|
pDesc->Buffer.FirstElement = 0;
|
|
|
|
pDesc->Buffer.NumElements = bufferDesc.ByteWidth / bufferDesc.StructureByteStride;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
} return E_INVALIDARG;
|
|
|
|
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
|
|
|
|
D3D11_TEXTURE1D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
pDesc->Format = resourceDesc.Format;
|
|
|
|
|
|
|
|
if (resourceDesc.ArraySize == 1) {
|
|
|
|
pDesc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1D;
|
|
|
|
pDesc->Texture1D.MipSlice = 0;
|
|
|
|
} else {
|
|
|
|
pDesc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1DARRAY;
|
|
|
|
pDesc->Texture1DArray.MipSlice = 0;
|
|
|
|
pDesc->Texture1DArray.FirstArraySlice = 0;
|
|
|
|
pDesc->Texture1DArray.ArraySize = resourceDesc.ArraySize;
|
|
|
|
}
|
|
|
|
} return S_OK;
|
|
|
|
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
|
|
|
|
D3D11_TEXTURE2D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
pDesc->Format = resourceDesc.Format;
|
|
|
|
|
|
|
|
if (resourceDesc.ArraySize == 1) {
|
|
|
|
pDesc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
|
|
|
|
pDesc->Texture2D.MipSlice = 0;
|
|
|
|
} else {
|
|
|
|
pDesc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
|
|
|
|
pDesc->Texture2DArray.MipSlice = 0;
|
|
|
|
pDesc->Texture2DArray.FirstArraySlice = 0;
|
|
|
|
pDesc->Texture2DArray.ArraySize = resourceDesc.ArraySize;
|
|
|
|
}
|
|
|
|
} return S_OK;
|
|
|
|
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE3D: {
|
|
|
|
D3D11_TEXTURE3D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture3D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
pDesc->Format = resourceDesc.Format;
|
|
|
|
pDesc->ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
|
|
|
|
pDesc->Texture3D.MipSlice = 0;
|
|
|
|
} return S_OK;
|
|
|
|
|
|
|
|
default:
|
|
|
|
Logger::err(str::format(
|
|
|
|
"D3D11: Unsupported dimension for unordered access view: ",
|
|
|
|
resourceDim));
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
2017-12-09 19:06:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-28 11:30:15 +01:00
|
|
|
HRESULT D3D11Device::GetRenderTargetViewDescFromResource(
|
|
|
|
ID3D11Resource* pResource,
|
|
|
|
D3D11_RENDER_TARGET_VIEW_DESC* pDesc) {
|
|
|
|
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
|
|
|
|
pResource->GetType(&resourceDim);
|
|
|
|
|
|
|
|
switch (resourceDim) {
|
2018-02-26 15:21:18 +01:00
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
|
|
|
|
D3D11_TEXTURE1D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
2018-02-26 17:00:24 +01:00
|
|
|
pDesc->Format = resourceDesc.Format;
|
|
|
|
|
2018-02-26 15:21:18 +01:00
|
|
|
if (resourceDesc.ArraySize == 1) {
|
|
|
|
pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
|
|
|
|
pDesc->Texture1D.MipSlice = 0;
|
|
|
|
} else {
|
|
|
|
pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
|
|
|
|
pDesc->Texture1DArray.MipSlice = 0;
|
|
|
|
pDesc->Texture1DArray.FirstArraySlice = 0;
|
|
|
|
pDesc->Texture1DArray.ArraySize = resourceDesc.ArraySize;
|
|
|
|
}
|
|
|
|
} return S_OK;
|
2018-01-28 11:30:15 +01:00
|
|
|
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
|
|
|
|
D3D11_TEXTURE2D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
pDesc->Format = resourceDesc.Format;
|
|
|
|
|
|
|
|
if (resourceDesc.SampleDesc.Count == 1) {
|
|
|
|
if (resourceDesc.ArraySize == 1) {
|
|
|
|
pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
|
|
|
pDesc->Texture2D.MipSlice = 0;
|
|
|
|
} else {
|
|
|
|
pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
|
|
|
pDesc->Texture2DArray.MipSlice = 0;
|
|
|
|
pDesc->Texture2DArray.FirstArraySlice = 0;
|
|
|
|
pDesc->Texture2DArray.ArraySize = resourceDesc.ArraySize;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (resourceDesc.ArraySize == 1) {
|
|
|
|
pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
|
|
|
|
} else {
|
|
|
|
pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
|
|
|
|
pDesc->Texture2DMSArray.FirstArraySlice = 0;
|
|
|
|
pDesc->Texture2DMSArray.ArraySize = resourceDesc.ArraySize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} return S_OK;
|
|
|
|
|
2018-02-14 03:16:53 +01:00
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE3D: {
|
|
|
|
D3D11_TEXTURE3D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture3D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
pDesc->Format = resourceDesc.Format;
|
|
|
|
pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
|
|
|
|
pDesc->Texture3D.MipSlice = 0;
|
|
|
|
pDesc->Texture3D.FirstWSlice = 0;
|
|
|
|
pDesc->Texture3D.WSize = resourceDesc.Depth;
|
|
|
|
} return S_OK;
|
|
|
|
|
2018-01-28 11:30:15 +01:00
|
|
|
default:
|
|
|
|
Logger::err(str::format(
|
|
|
|
"D3D11: Unsupported dimension for render target view: ",
|
|
|
|
resourceDim));
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT D3D11Device::GetDepthStencilViewDescFromResource(
|
|
|
|
ID3D11Resource* pResource,
|
|
|
|
D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc) {
|
|
|
|
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
|
|
|
|
pResource->GetType(&resourceDim);
|
|
|
|
|
|
|
|
switch (resourceDim) {
|
2018-02-26 15:21:18 +01:00
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
|
|
|
|
D3D11_TEXTURE1D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
2018-02-26 17:00:24 +01:00
|
|
|
pDesc->Format = resourceDesc.Format;
|
|
|
|
|
2018-02-26 15:21:18 +01:00
|
|
|
if (resourceDesc.ArraySize == 1) {
|
|
|
|
pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D;
|
|
|
|
pDesc->Texture1D.MipSlice = 0;
|
|
|
|
} else {
|
|
|
|
pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1DARRAY;
|
|
|
|
pDesc->Texture1DArray.MipSlice = 0;
|
|
|
|
pDesc->Texture1DArray.FirstArraySlice = 0;
|
|
|
|
pDesc->Texture1DArray.ArraySize = resourceDesc.ArraySize;
|
|
|
|
}
|
|
|
|
} return S_OK;
|
2018-01-28 11:30:15 +01:00
|
|
|
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
|
|
|
|
D3D11_TEXTURE2D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
pDesc->Format = resourceDesc.Format;
|
|
|
|
|
|
|
|
if (resourceDesc.SampleDesc.Count == 1) {
|
|
|
|
if (resourceDesc.ArraySize == 1) {
|
|
|
|
pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
|
|
|
pDesc->Texture2D.MipSlice = 0;
|
|
|
|
} else {
|
|
|
|
pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
|
|
|
pDesc->Texture2DArray.MipSlice = 0;
|
|
|
|
pDesc->Texture2DArray.FirstArraySlice = 0;
|
|
|
|
pDesc->Texture2DArray.ArraySize = resourceDesc.ArraySize;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (resourceDesc.ArraySize == 1) {
|
|
|
|
pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
|
|
|
|
} else {
|
|
|
|
pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
|
|
|
|
pDesc->Texture2DMSArray.FirstArraySlice = 0;
|
|
|
|
pDesc->Texture2DMSArray.ArraySize = resourceDesc.ArraySize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} return S_OK;
|
|
|
|
|
|
|
|
default:
|
|
|
|
Logger::err(str::format(
|
|
|
|
"D3D11: Unsupported dimension for depth stencil view: ",
|
|
|
|
resourceDim));
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-17 15:19:55 +01:00
|
|
|
HRESULT D3D11Device::SetShaderResourceViewDescUnspecValues(
|
|
|
|
ID3D11Resource* pResource,
|
|
|
|
D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc) {
|
|
|
|
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
|
|
|
|
pResource->GetType(&resourceDim);
|
|
|
|
|
|
|
|
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
|
|
|
|
uint32_t mipLevels = 0;
|
|
|
|
uint32_t numLayers = 0;
|
|
|
|
|
|
|
|
switch (resourceDim) {
|
|
|
|
case D3D11_RESOURCE_DIMENSION_BUFFER: {
|
|
|
|
if (pDesc->ViewDimension != D3D11_SRV_DIMENSION_BUFFER
|
|
|
|
&& pDesc->ViewDimension != D3D11_SRV_DIMENSION_BUFFEREX) {
|
|
|
|
Logger::err("D3D11: Incompatible view dimension for Buffer");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
|
|
|
|
D3D11_TEXTURE1D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
if (pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE1D
|
|
|
|
&& pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE1DARRAY) {
|
|
|
|
Logger::err("D3D11: Incompatible view dimension for Texture1D");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
format = resourceDesc.Format;
|
|
|
|
mipLevels = resourceDesc.MipLevels;
|
|
|
|
numLayers = resourceDesc.ArraySize;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
|
|
|
|
D3D11_TEXTURE2D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
if (pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE2D
|
|
|
|
&& pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE2DARRAY
|
|
|
|
&& pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE2DMS
|
|
|
|
&& pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY
|
|
|
|
&& pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURECUBE
|
|
|
|
&& pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURECUBEARRAY) {
|
|
|
|
Logger::err("D3D11: Incompatible view dimension for Texture2D");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
format = resourceDesc.Format;
|
|
|
|
mipLevels = resourceDesc.MipLevels;
|
|
|
|
numLayers = resourceDesc.ArraySize;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE3D: {
|
|
|
|
D3D11_TEXTURE3D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture3D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
if (pDesc->ViewDimension != D3D11_SRV_DIMENSION_TEXTURE3D) {
|
|
|
|
Logger::err("D3D11: Incompatible view dimension for Texture3D");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
format = resourceDesc.Format;
|
|
|
|
mipLevels = resourceDesc.MipLevels;
|
|
|
|
numLayers = 1;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pDesc->Format == DXGI_FORMAT_UNKNOWN)
|
|
|
|
pDesc->Format = format;
|
|
|
|
|
|
|
|
switch (pDesc->ViewDimension) {
|
|
|
|
case D3D11_SRV_DIMENSION_TEXTURE1D:
|
|
|
|
if (pDesc->Texture1D.MipLevels == D3D11_DXVK_USE_REMAINING_LEVELS)
|
|
|
|
pDesc->Texture1D.MipLevels = mipLevels - pDesc->Texture1D.MostDetailedMip;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
|
|
|
|
if (pDesc->Texture1DArray.MipLevels == D3D11_DXVK_USE_REMAINING_LEVELS)
|
|
|
|
pDesc->Texture1DArray.MipLevels = mipLevels - pDesc->Texture1DArray.MostDetailedMip;
|
|
|
|
if (pDesc->Texture1DArray.ArraySize == D3D11_DXVK_USE_REMAINING_LAYERS)
|
|
|
|
pDesc->Texture1DArray.ArraySize = numLayers - pDesc->Texture1DArray.FirstArraySlice;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_SRV_DIMENSION_TEXTURE2D:
|
|
|
|
if (pDesc->Texture2D.MipLevels == D3D11_DXVK_USE_REMAINING_LEVELS)
|
|
|
|
pDesc->Texture2D.MipLevels = mipLevels - pDesc->Texture2D.MostDetailedMip;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
|
|
|
|
if (pDesc->Texture2DArray.MipLevels == D3D11_DXVK_USE_REMAINING_LEVELS)
|
|
|
|
pDesc->Texture2DArray.MipLevels = mipLevels - pDesc->Texture2DArray.MostDetailedMip;
|
|
|
|
if (pDesc->Texture2DArray.ArraySize == D3D11_DXVK_USE_REMAINING_LAYERS)
|
|
|
|
pDesc->Texture2DArray.ArraySize = numLayers - pDesc->Texture2DArray.FirstArraySlice;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
|
|
|
|
if (pDesc->Texture2DMSArray.ArraySize == D3D11_DXVK_USE_REMAINING_LAYERS)
|
|
|
|
pDesc->Texture2DMSArray.ArraySize = numLayers - pDesc->Texture2DMSArray.FirstArraySlice;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_SRV_DIMENSION_TEXTURECUBE:
|
|
|
|
if (pDesc->TextureCube.MipLevels == D3D11_DXVK_USE_REMAINING_LEVELS)
|
|
|
|
pDesc->TextureCube.MipLevels = mipLevels - pDesc->TextureCube.MostDetailedMip;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
|
|
|
|
if (pDesc->TextureCubeArray.MipLevels == D3D11_DXVK_USE_REMAINING_LEVELS)
|
|
|
|
pDesc->TextureCubeArray.MipLevels = mipLevels - pDesc->TextureCubeArray.MostDetailedMip;
|
|
|
|
if (pDesc->TextureCubeArray.NumCubes == D3D11_DXVK_USE_REMAINING_LAYERS)
|
|
|
|
pDesc->TextureCubeArray.NumCubes = (mipLevels - pDesc->TextureCubeArray.First2DArrayFace / 6);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_SRV_DIMENSION_TEXTURE3D:
|
|
|
|
if (pDesc->Texture3D.MipLevels == D3D11_DXVK_USE_REMAINING_LEVELS)
|
|
|
|
pDesc->Texture3D.MipLevels = mipLevels - pDesc->Texture3D.MostDetailedMip;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-28 11:30:15 +01:00
|
|
|
HRESULT D3D11Device::SetUnorderedAccessViewDescUnspecValues(
|
2017-12-09 19:06:51 +01:00
|
|
|
ID3D11Resource* pResource,
|
2018-01-28 11:30:15 +01:00
|
|
|
D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc) {
|
2017-12-09 19:06:51 +01:00
|
|
|
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
|
|
|
|
pResource->GetType(&resourceDim);
|
|
|
|
|
2018-01-28 11:30:15 +01:00
|
|
|
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
|
|
|
|
uint32_t numLayers = 0;
|
|
|
|
|
2017-12-09 19:36:38 +01:00
|
|
|
switch (resourceDim) {
|
2018-01-28 11:30:15 +01:00
|
|
|
case D3D11_RESOURCE_DIMENSION_BUFFER: {
|
|
|
|
if (pDesc->ViewDimension != D3D11_UAV_DIMENSION_BUFFER) {
|
|
|
|
Logger::err("D3D11: Incompatible view dimension for Buffer");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
} break;
|
2017-12-09 19:36:38 +01:00
|
|
|
|
2018-01-28 11:30:15 +01:00
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
|
|
|
|
D3D11_TEXTURE1D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
|
2017-12-09 19:36:38 +01:00
|
|
|
|
2018-01-28 11:30:15 +01:00
|
|
|
if (pDesc->ViewDimension != D3D11_UAV_DIMENSION_TEXTURE1D
|
|
|
|
&& pDesc->ViewDimension != D3D11_UAV_DIMENSION_TEXTURE1DARRAY) {
|
|
|
|
Logger::err("D3D11: Incompatible view dimension for Texture1D");
|
|
|
|
return E_INVALIDARG;
|
2017-12-09 19:36:38 +01:00
|
|
|
}
|
|
|
|
|
2018-01-28 11:30:15 +01:00
|
|
|
format = resourceDesc.Format;
|
|
|
|
numLayers = resourceDesc.ArraySize;
|
|
|
|
} break;
|
2017-12-09 19:36:38 +01:00
|
|
|
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
|
|
|
|
D3D11_TEXTURE2D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
2018-01-28 11:30:15 +01:00
|
|
|
if (pDesc->ViewDimension != D3D11_UAV_DIMENSION_TEXTURE2D
|
|
|
|
&& pDesc->ViewDimension != D3D11_UAV_DIMENSION_TEXTURE2DARRAY) {
|
|
|
|
Logger::err("D3D11: Incompatible view dimension for Texture2D");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
2017-12-09 19:36:38 +01:00
|
|
|
|
2018-01-28 11:30:15 +01:00
|
|
|
format = resourceDesc.Format;
|
|
|
|
numLayers = resourceDesc.ArraySize;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE3D: {
|
|
|
|
D3D11_TEXTURE3D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture3D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
if (pDesc->ViewDimension != D3D11_UAV_DIMENSION_TEXTURE3D) {
|
|
|
|
Logger::err("D3D11: Incompatible view dimension for Texture3D");
|
|
|
|
return E_INVALIDARG;
|
2017-12-09 19:36:38 +01:00
|
|
|
}
|
|
|
|
|
2018-01-28 11:30:15 +01:00
|
|
|
format = resourceDesc.Format;
|
|
|
|
numLayers = resourceDesc.Depth >> pDesc->Texture3D.MipSlice;
|
|
|
|
} break;
|
|
|
|
|
2017-12-09 19:36:38 +01:00
|
|
|
default:
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
2018-01-28 11:30:15 +01:00
|
|
|
|
|
|
|
if (pDesc->Format == DXGI_FORMAT_UNKNOWN)
|
|
|
|
pDesc->Format = format;
|
|
|
|
|
|
|
|
switch (pDesc->ViewDimension) {
|
|
|
|
case D3D11_UAV_DIMENSION_TEXTURE1DARRAY:
|
|
|
|
if (pDesc->Texture1DArray.ArraySize == D3D11_DXVK_USE_REMAINING_LAYERS)
|
|
|
|
pDesc->Texture1DArray.ArraySize = numLayers - pDesc->Texture1DArray.FirstArraySlice;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_UAV_DIMENSION_TEXTURE2DARRAY:
|
|
|
|
if (pDesc->Texture2DArray.ArraySize == D3D11_DXVK_USE_REMAINING_LAYERS)
|
|
|
|
pDesc->Texture2DArray.ArraySize = numLayers - pDesc->Texture2DArray.FirstArraySlice;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_UAV_DIMENSION_TEXTURE3D:
|
|
|
|
if (pDesc->Texture3D.WSize == D3D11_DXVK_USE_REMAINING_LAYERS)
|
|
|
|
pDesc->Texture3D.WSize = numLayers - pDesc->Texture3D.FirstWSlice;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
2017-12-09 19:06:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-02-14 01:29:50 +01:00
|
|
|
HRESULT D3D11Device::SetRenderTargetViewDescUnspecValues(
|
|
|
|
ID3D11Resource* pResource,
|
|
|
|
D3D11_RENDER_TARGET_VIEW_DESC* pDesc) {
|
|
|
|
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
|
|
|
|
pResource->GetType(&resourceDim);
|
|
|
|
|
|
|
|
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
|
|
|
|
uint32_t numLayers = 0;
|
|
|
|
|
|
|
|
switch (resourceDim) {
|
|
|
|
case D3D11_RESOURCE_DIMENSION_BUFFER: {
|
|
|
|
if (pDesc->ViewDimension != D3D11_RTV_DIMENSION_BUFFER) {
|
|
|
|
Logger::err("D3D11: Incompatible view dimension for Buffer");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
|
|
|
|
D3D11_TEXTURE1D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
if (pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE1D
|
|
|
|
&& pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE1DARRAY) {
|
|
|
|
Logger::err("D3D11: Incompatible view dimension for Texture1D");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
format = resourceDesc.Format;
|
|
|
|
numLayers = resourceDesc.ArraySize;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
|
|
|
|
D3D11_TEXTURE2D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
if (pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE2D
|
|
|
|
&& pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE2DARRAY
|
|
|
|
&& pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE2DMS
|
|
|
|
&& pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY) {
|
|
|
|
Logger::err("D3D11: Incompatible view dimension for Texture2D");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
format = resourceDesc.Format;
|
|
|
|
numLayers = resourceDesc.ArraySize;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE3D: {
|
|
|
|
D3D11_TEXTURE3D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture3D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
if (pDesc->ViewDimension != D3D11_RTV_DIMENSION_TEXTURE3D) {
|
|
|
|
Logger::err("D3D11: Incompatible view dimension for Texture3D");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
format = resourceDesc.Format;
|
2018-02-14 03:16:53 +01:00
|
|
|
numLayers = resourceDesc.Depth;
|
2018-02-14 01:29:50 +01:00
|
|
|
} break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pDesc->Format == DXGI_FORMAT_UNKNOWN)
|
|
|
|
pDesc->Format = format;
|
|
|
|
|
|
|
|
switch (pDesc->ViewDimension) {
|
|
|
|
case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
|
|
|
|
if (pDesc->Texture1DArray.ArraySize == D3D11_DXVK_USE_REMAINING_LAYERS)
|
|
|
|
pDesc->Texture1DArray.ArraySize = numLayers - pDesc->Texture1DArray.FirstArraySlice;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
|
|
|
|
if (pDesc->Texture2DArray.ArraySize == D3D11_DXVK_USE_REMAINING_LAYERS)
|
|
|
|
pDesc->Texture2DArray.ArraySize = numLayers - pDesc->Texture2DArray.FirstArraySlice;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
|
|
|
|
if (pDesc->Texture2DMSArray.ArraySize == D3D11_DXVK_USE_REMAINING_LAYERS)
|
|
|
|
pDesc->Texture2DMSArray.ArraySize = numLayers - pDesc->Texture2DMSArray.FirstArraySlice;
|
|
|
|
break;
|
|
|
|
|
2018-02-14 03:16:53 +01:00
|
|
|
case D3D11_RTV_DIMENSION_TEXTURE3D:
|
|
|
|
if (pDesc->Texture3D.WSize == D3D11_DXVK_USE_REMAINING_LAYERS)
|
|
|
|
pDesc->Texture3D.WSize = numLayers - pDesc->Texture3D.FirstWSlice;
|
|
|
|
break;
|
|
|
|
|
2018-02-14 01:29:50 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT D3D11Device::SetDepthStencilViewDescUnspecValues(
|
|
|
|
ID3D11Resource* pResource,
|
|
|
|
D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc) {
|
|
|
|
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
|
|
|
|
pResource->GetType(&resourceDim);
|
|
|
|
|
|
|
|
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
|
|
|
|
uint32_t numLayers = 0;
|
|
|
|
|
|
|
|
switch (resourceDim) {
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
|
|
|
|
D3D11_TEXTURE1D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture1D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
if (pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE1D
|
|
|
|
&& pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE1DARRAY) {
|
|
|
|
Logger::err("D3D11: Incompatible view dimension for Texture1D");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
format = resourceDesc.Format;
|
|
|
|
numLayers = resourceDesc.ArraySize;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
|
|
|
|
D3D11_TEXTURE2D_DESC resourceDesc;
|
|
|
|
static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
|
|
|
|
|
|
|
|
if (pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE2D
|
|
|
|
&& pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE2DARRAY
|
|
|
|
&& pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE2DMS
|
|
|
|
&& pDesc->ViewDimension != D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY) {
|
|
|
|
Logger::err("D3D11: Incompatible view dimension for Texture2D");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
format = resourceDesc.Format;
|
|
|
|
numLayers = resourceDesc.ArraySize;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pDesc->Format == DXGI_FORMAT_UNKNOWN)
|
|
|
|
pDesc->Format = format;
|
|
|
|
|
|
|
|
switch (pDesc->ViewDimension) {
|
|
|
|
case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
|
|
|
|
if (pDesc->Texture1DArray.ArraySize == D3D11_DXVK_USE_REMAINING_LAYERS)
|
|
|
|
pDesc->Texture1DArray.ArraySize = numLayers - pDesc->Texture1DArray.FirstArraySlice;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
|
|
|
|
if (pDesc->Texture2DArray.ArraySize == D3D11_DXVK_USE_REMAINING_LAYERS)
|
|
|
|
pDesc->Texture2DArray.ArraySize = numLayers - pDesc->Texture2DArray.FirstArraySlice;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
|
|
|
|
if (pDesc->Texture2DMSArray.ArraySize == D3D11_DXVK_USE_REMAINING_LAYERS)
|
|
|
|
pDesc->Texture2DMSArray.ArraySize = numLayers - pDesc->Texture2DMSArray.FirstArraySlice;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-09 20:49:56 +01:00
|
|
|
VkSamplerAddressMode D3D11Device::DecodeAddressMode(
|
|
|
|
D3D11_TEXTURE_ADDRESS_MODE mode) const {
|
|
|
|
switch (mode) {
|
|
|
|
case D3D11_TEXTURE_ADDRESS_WRAP:
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
|
|
|
|
|
|
case D3D11_TEXTURE_ADDRESS_MIRROR:
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
|
|
|
|
|
|
|
|
case D3D11_TEXTURE_ADDRESS_CLAMP:
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
|
|
|
|
|
|
|
case D3D11_TEXTURE_ADDRESS_BORDER:
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
|
|
|
|
|
|
|
case D3D11_TEXTURE_ADDRESS_MIRROR_ONCE:
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
|
|
|
|
|
|
|
|
default:
|
|
|
|
Logger::err(str::format("D3D11: Unsupported address mode: ", mode));
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-19 11:05:41 +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;
|
2017-12-19 11:05:41 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-01-11 12:23:55 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-01-13 23:40:17 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-01-30 12:19:53 +01:00
|
|
|
|
|
|
|
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
|
|
|
}
|