diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 53307467..8b14433e 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -266,18 +266,16 @@ namespace dxvk { // Only 2D textures and 2D texture arrays are allowed if (resourceDim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) { - Logger::err("D3D11Device::CreateRenderTargetView: Unsupported resource type"); + Logger::err("D3D11: Unsupported resource type for render target views"); return E_INVALIDARG; } - // Make sure we can retrieve the image object + // Retrieve the image that we are going to create the view for auto texture = static_cast(pResource); - - // Image that we are going to create the view for const Rc image = texture->GetDXVKImage(); // The view description is optional. If not defined, it - // will use the resource's format and all subresources. + // will use the resource's format and all array layers. D3D11_RENDER_TARGET_VIEW_DESC desc; if (pDesc != nullptr) { @@ -372,7 +370,7 @@ namespace dxvk { default: Logger::err(str::format( - "D3D11Device::CreateRenderTargetView: pDesc->ViewDimension not supported: ", + "D3D11: pDesc->ViewDimension not supported for render target views: ", desc.ViewDimension)); return E_INVALIDARG; } @@ -396,8 +394,134 @@ namespace dxvk { ID3D11Resource* pResource, const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc, ID3D11DepthStencilView** ppDepthStencilView) { - Logger::err("D3D11Device::CreateDepthStencilView: Not implemented"); - return E_NOTIMPL; + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + + // Only 2D textures and 2D texture arrays are allowed + if (resourceDim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) { + Logger::err("D3D11: Unsupported resource type for depth-stencil views"); + return E_INVALIDARG; + } + + // Retrieve the image that we are going to create the view for + auto texture = static_cast(pResource); + const Rc image = texture->GetDXVKImage(); + + // 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; + + if (pDesc != nullptr) { + desc = *pDesc; + } else { + D3D11_TEXTURE2D_DESC texDesc; + texture->GetDesc(&texDesc); + + // Select the view dimension based on the + // texture's array size and sample count. + const std::array viewDims = { + D3D11_DSV_DIMENSION_TEXTURE2D, + D3D11_DSV_DIMENSION_TEXTURE2DARRAY, + D3D11_DSV_DIMENSION_TEXTURE2DMS, + D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY, + }; + + uint32_t viewDimIndex = 0; + + if (texDesc.ArraySize > 1) + viewDimIndex |= 0x1; + + if (texDesc.SampleDesc.Count > 1) + viewDimIndex |= 0x2; + + // Fill the correct union member + desc.ViewDimension = viewDims.at(viewDimIndex); + desc.Format = texDesc.Format; + + switch (desc.ViewDimension) { + case D3D11_DSV_DIMENSION_TEXTURE2D: + desc.Texture2D.MipSlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: + desc.Texture2DArray.MipSlice = 0; + desc.Texture2DArray.FirstArraySlice = 0; + desc.Texture2DArray.ArraySize = texDesc.ArraySize; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMS: + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: + desc.Texture2DMSArray.FirstArraySlice = 0; + desc.Texture2DMSArray.ArraySize = texDesc.ArraySize; + break; + + default: + Logger::err("D3D11Device::CreateDepthStencilView: Internal error"); + return DXGI_ERROR_DRIVER_INTERNAL_ERROR; + } + } + + // Fill in Vulkan image view info + // TODO Implement some sort of format reflection + DxvkImageViewCreateInfo viewInfo; + viewInfo.format = m_dxgiAdapter->LookupFormat(desc.Format).actual; + viewInfo.aspect = VK_IMAGE_ASPECT_DEPTH_BIT + | VK_IMAGE_ASPECT_STENCIL_BIT; + + switch (desc.ViewDimension) { + case D3D11_DSV_DIMENSION_TEXTURE2D: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.minLevel = desc.Texture2D.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + viewInfo.minLevel = desc.Texture2DArray.MipSlice; + viewInfo.numLevels = 1; + viewInfo.minLayer = desc.Texture2DArray.FirstArraySlice; + viewInfo.numLayers = desc.Texture2DArray.ArraySize; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMS: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.minLevel = 0; + viewInfo.numLevels = 1; + viewInfo.minLayer = 0; + viewInfo.numLayers = 1; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: + viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + viewInfo.minLevel = 0; + viewInfo.numLevels = 1; + viewInfo.minLayer = desc.Texture2DArray.FirstArraySlice; + viewInfo.numLayers = desc.Texture2DArray.ArraySize; + break; + + default: + Logger::err(str::format( + "D3D11: pDesc->ViewDimension not supported for depth-stencil views: ", + desc.ViewDimension)); + return E_INVALIDARG; + } + + // Create the actual image view if requested + if (ppDepthStencilView == nullptr) + return S_OK; + + try { + Rc view = m_dxvkDevice->createImageView(image, viewInfo); + *ppDepthStencilView = ref(new D3D11DepthStencilView(this, pResource, desc, view)); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return DXGI_ERROR_DRIVER_INTERNAL_ERROR; + } } diff --git a/src/d3d11/d3d11_view.cpp b/src/d3d11/d3d11_view.cpp index 5f32a96a..551cfdc1 100644 --- a/src/d3d11/d3d11_view.cpp +++ b/src/d3d11/d3d11_view.cpp @@ -51,4 +51,55 @@ namespace dxvk { return m_view; } + + + + D3D11DepthStencilView::D3D11DepthStencilView( + D3D11Device* device, + ID3D11Resource* resource, + const D3D11_DEPTH_STENCIL_VIEW_DESC& desc, + Rc view) + : m_device (device), + m_resource(resource), + m_desc (desc), + m_view (view) { + + } + + + D3D11DepthStencilView::~D3D11DepthStencilView() { + + } + + + HRESULT D3D11DepthStencilView::QueryInterface(REFIID riid, void** ppvObject) { + COM_QUERY_IFACE(riid, ppvObject, IUnknown); + COM_QUERY_IFACE(riid, ppvObject, ID3D11DeviceChild); + COM_QUERY_IFACE(riid, ppvObject, ID3D11View); + COM_QUERY_IFACE(riid, ppvObject, ID3D11DepthStencilView); + + Logger::warn("D3D11DepthStencilView::QueryInterface: Unknown interface query"); + return E_NOINTERFACE; + } + + + void D3D11DepthStencilView::GetDevice(ID3D11Device** ppDevice) { + *ppDevice = ref(m_device); + } + + + void D3D11DepthStencilView::GetResource(ID3D11Resource **ppResource) { + *ppResource = m_resource.ref(); + } + + + void D3D11DepthStencilView::GetDesc(D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc) { + *pDesc = m_desc; + } + + + Rc D3D11DepthStencilView::GetDXVKImageView() { + return m_view; + } + } diff --git a/src/d3d11/d3d11_view.h b/src/d3d11/d3d11_view.h index 307f4e20..440a35f1 100644 --- a/src/d3d11/d3d11_view.h +++ b/src/d3d11/d3d11_view.h @@ -44,4 +44,42 @@ namespace dxvk { }; + class D3D11DepthStencilView : public D3D11DeviceChild { + + public: + + D3D11DepthStencilView( + D3D11Device* device, + ID3D11Resource* resource, + const D3D11_DEPTH_STENCIL_VIEW_DESC& desc, + Rc view); + ~D3D11DepthStencilView(); + + HRESULT QueryInterface( + REFIID riid, + void** ppvObject) final; + + void GetDevice( + ID3D11Device **ppDevice) final; + + void GetResource( + ID3D11Resource **ppResource) final; + + void GetDesc( + D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc) final; + + Rc GetDXVKImageView(); + + private: + + D3D11Device* const m_device; + Com m_resource; + + D3D11_DEPTH_STENCIL_VIEW_DESC m_desc; + Rc m_view; + + }; + + + }