#include #include "d3d11_context_imm.h" #include "d3d11_video.h" #include #include namespace dxvk { D3D11VideoProcessorEnumerator::D3D11VideoProcessorEnumerator( D3D11Device* pDevice, const D3D11_VIDEO_PROCESSOR_CONTENT_DESC& Desc) : D3D11DeviceChild(pDevice), m_desc(Desc) { } D3D11VideoProcessorEnumerator::~D3D11VideoProcessorEnumerator() { } HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::QueryInterface( REFIID riid, void** ppvObject) { if (riid == __uuidof(IUnknown) || riid == __uuidof(ID3D11DeviceChild) || riid == __uuidof(ID3D11VideoProcessorEnumerator)) { *ppvObject = ref(this); return S_OK; } Logger::warn("D3D11VideoProcessorEnumerator::QueryInterface: Unknown interface query"); Logger::warn(str::format(riid)); return E_NOINTERFACE; } HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorContentDesc( D3D11_VIDEO_PROCESSOR_CONTENT_DESC* pContentDesc) { *pContentDesc = m_desc; return S_OK; } HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::CheckVideoProcessorFormat( DXGI_FORMAT Format, UINT* pFlags) { Logger::err("D3D11VideoProcessorEnumerator::CheckVideoProcessorFormat: Stub"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorCaps( D3D11_VIDEO_PROCESSOR_CAPS* pCaps) { Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorCaps: Stub"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorRateConversionCaps( UINT TypeIndex, D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS* pCaps) { Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorRateConversionCaps: Stub"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorCustomRate( UINT TypeIndex, UINT CustomRateIndex, D3D11_VIDEO_PROCESSOR_CUSTOM_RATE* pRate) { Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorCustomRate: Stub"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE D3D11VideoProcessorEnumerator::GetVideoProcessorFilterRange( D3D11_VIDEO_PROCESSOR_FILTER Filter, D3D11_VIDEO_PROCESSOR_FILTER_RANGE* pRange) { Logger::err("D3D11VideoProcessorEnumerator::GetVideoProcessorFilterRange: Stub"); return E_NOTIMPL; } D3D11VideoProcessor::D3D11VideoProcessor( D3D11Device* pDevice, D3D11VideoProcessorEnumerator* pEnumerator, UINT RateConversionIndex) : D3D11DeviceChild(pDevice), m_enumerator(pEnumerator), m_rateConversionIndex(RateConversionIndex) { } D3D11VideoProcessor::~D3D11VideoProcessor() { } HRESULT STDMETHODCALLTYPE D3D11VideoProcessor::QueryInterface( REFIID riid, void** ppvObject) { if (riid == __uuidof(IUnknown) || riid == __uuidof(ID3D11DeviceChild) || riid == __uuidof(ID3D11VideoProcessor)) { *ppvObject = ref(this); return S_OK; } Logger::warn("D3D11VideoProcessor::QueryInterface: Unknown interface query"); Logger::warn(str::format(riid)); return E_NOINTERFACE; } void STDMETHODCALLTYPE D3D11VideoProcessor::GetContentDesc( D3D11_VIDEO_PROCESSOR_CONTENT_DESC *pDesc) { m_enumerator->GetVideoProcessorContentDesc(pDesc); } void STDMETHODCALLTYPE D3D11VideoProcessor::GetRateConversionCaps( D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS *pCaps) { m_enumerator->GetVideoProcessorRateConversionCaps(m_rateConversionIndex, pCaps); } D3D11VideoProcessorInputView::D3D11VideoProcessorInputView( D3D11Device* pDevice, ID3D11Resource* pResource, const D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC& Desc) : D3D11DeviceChild(pDevice), m_resource(pResource), m_desc(Desc) { D3D11_COMMON_RESOURCE_DESC resourceDesc = { }; GetCommonResourceDesc(pResource, &resourceDesc); Rc dxvkImage = GetCommonTexture(pResource)->GetImage(); if (!(dxvkImage->info().usage & VK_IMAGE_USAGE_SAMPLED_BIT)) { DxvkImageCreateInfo info = dxvkImage->info(); info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; info.access = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT; info.tiling = VK_IMAGE_TILING_OPTIMAL; info.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; info.shared = VK_FALSE; dxvkImage = m_copy = pDevice->GetDXVKDevice()->createImage(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); } DXGI_VK_FORMAT_INFO formatInfo = pDevice->LookupFormat(resourceDesc.Format, DXGI_VK_FORMAT_MODE_COLOR); DXGI_VK_FORMAT_FAMILY formatFamily = pDevice->LookupFamily(resourceDesc.Format, DXGI_VK_FORMAT_MODE_COLOR); VkImageAspectFlags aspectMask = lookupFormatInfo(formatInfo.Format)->aspectMask; DxvkImageViewCreateInfo viewInfo; viewInfo.format = formatInfo.Format; viewInfo.swizzle = formatInfo.Swizzle; viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; switch (m_desc.ViewDimension) { case D3D11_VPIV_DIMENSION_TEXTURE2D: viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; viewInfo.minLevel = m_desc.Texture2D.MipSlice; viewInfo.numLevels = 1; viewInfo.minLayer = 0; viewInfo.numLayers = 1; break; case D3D11_VPIV_DIMENSION_UNKNOWN: throw DxvkError("Invalid view dimension"); } m_subresources.aspectMask = aspectMask; m_subresources.baseArrayLayer = viewInfo.minLayer; m_subresources.layerCount = viewInfo.numLayers; m_subresources.mipLevel = viewInfo.minLevel; for (uint32_t i = 0; aspectMask && i < m_views.size(); i++) { viewInfo.aspect = vk::getNextAspect(aspectMask); if (viewInfo.aspect != VK_IMAGE_ASPECT_COLOR_BIT) viewInfo.format = formatFamily.Formats[i]; m_views[i] = pDevice->GetDXVKDevice()->createImageView(dxvkImage, viewInfo); } m_isYCbCr = IsYCbCrFormat(resourceDesc.Format); } D3D11VideoProcessorInputView::~D3D11VideoProcessorInputView() { } bool D3D11VideoProcessorInputView::IsYCbCrFormat(DXGI_FORMAT Format) { static const std::array s_formats = {{ DXGI_FORMAT_NV12, DXGI_FORMAT_YUY2, DXGI_FORMAT_AYUV, }}; return std::find(s_formats.begin(), s_formats.end(), Format) != s_formats.end(); } HRESULT STDMETHODCALLTYPE D3D11VideoProcessorInputView::QueryInterface( REFIID riid, void** ppvObject) { if (riid == __uuidof(IUnknown) || riid == __uuidof(ID3D11DeviceChild) || riid == __uuidof(ID3D11View) || riid == __uuidof(ID3D11VideoProcessorInputView)) { *ppvObject = ref(this); return S_OK; } Logger::warn("D3D11VideoProcessorInputView::QueryInterface: Unknown interface query"); Logger::warn(str::format(riid)); return E_NOINTERFACE; } void STDMETHODCALLTYPE D3D11VideoProcessorInputView::GetResource( ID3D11Resource** ppResource) { *ppResource = m_resource.ref(); } void STDMETHODCALLTYPE D3D11VideoProcessorInputView::GetDesc( D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC* pDesc) { *pDesc = m_desc; } D3D11VideoProcessorOutputView::D3D11VideoProcessorOutputView( D3D11Device* pDevice, ID3D11Resource* pResource, const D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC& Desc) : D3D11DeviceChild(pDevice), m_resource(pResource), m_desc(Desc) { D3D11_COMMON_RESOURCE_DESC resourceDesc = { }; GetCommonResourceDesc(pResource, &resourceDesc); DXGI_VK_FORMAT_INFO formatInfo = pDevice->LookupFormat( resourceDesc.Format, DXGI_VK_FORMAT_MODE_COLOR); DxvkImageViewCreateInfo viewInfo; viewInfo.format = formatInfo.Format; viewInfo.aspect = lookupFormatInfo(viewInfo.format)->aspectMask; viewInfo.swizzle = formatInfo.Swizzle; viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; switch (m_desc.ViewDimension) { case D3D11_VPOV_DIMENSION_TEXTURE2D: viewInfo.type = VK_IMAGE_VIEW_TYPE_2D; viewInfo.minLevel = m_desc.Texture2D.MipSlice; viewInfo.numLevels = 1; viewInfo.minLayer = 0; viewInfo.numLayers = 1; break; case D3D11_VPOV_DIMENSION_TEXTURE2DARRAY: viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; viewInfo.minLevel = m_desc.Texture2DArray.MipSlice; viewInfo.numLevels = 1; viewInfo.minLayer = m_desc.Texture2DArray.FirstArraySlice; viewInfo.numLayers = m_desc.Texture2DArray.ArraySize; break; case D3D11_VPOV_DIMENSION_UNKNOWN: throw DxvkError("Invalid view dimension"); } m_view = pDevice->GetDXVKDevice()->createImageView( GetCommonTexture(pResource)->GetImage(), viewInfo); } D3D11VideoProcessorOutputView::~D3D11VideoProcessorOutputView() { } HRESULT STDMETHODCALLTYPE D3D11VideoProcessorOutputView::QueryInterface( REFIID riid, void** ppvObject) { if (riid == __uuidof(IUnknown) || riid == __uuidof(ID3D11DeviceChild) || riid == __uuidof(ID3D11View) || riid == __uuidof(ID3D11VideoProcessorOutputView)) { *ppvObject = ref(this); return S_OK; } Logger::warn("D3D11VideoProcessorOutputView::QueryInterface: Unknown interface query"); Logger::warn(str::format(riid)); return E_NOINTERFACE; } void STDMETHODCALLTYPE D3D11VideoProcessorOutputView::GetResource( ID3D11Resource** ppResource) { *ppResource = m_resource.ref(); } void STDMETHODCALLTYPE D3D11VideoProcessorOutputView::GetDesc( D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* pDesc) { *pDesc = m_desc; } D3D11VideoContext::D3D11VideoContext( D3D11ImmediateContext* pContext, const Rc& Device) : m_ctx(pContext) { SpirvCodeBuffer vsCode(d3d11_video_blit_vert); SpirvCodeBuffer fsCode(d3d11_video_blit_frag); const std::array fsBindings = {{ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, VK_IMAGE_VIEW_TYPE_MAX_ENUM, VK_SHADER_STAGE_FRAGMENT_BIT, VK_ACCESS_UNIFORM_READ_BIT }, { VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_IMAGE_VIEW_TYPE_MAX_ENUM, VK_SHADER_STAGE_FRAGMENT_BIT, 0 }, { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 2, VK_IMAGE_VIEW_TYPE_2D, VK_SHADER_STAGE_FRAGMENT_BIT, VK_ACCESS_SHADER_READ_BIT }, { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 3, VK_IMAGE_VIEW_TYPE_2D, VK_SHADER_STAGE_FRAGMENT_BIT, VK_ACCESS_SHADER_READ_BIT }, }}; DxvkShaderCreateInfo vsInfo; vsInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; vsInfo.outputMask = 0x1; m_vs = new DxvkShader(vsInfo, std::move(vsCode)); DxvkShaderCreateInfo fsInfo; fsInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; fsInfo.bindingCount = fsBindings.size(); fsInfo.bindings = fsBindings.data(); fsInfo.inputMask = 0x1; fsInfo.outputMask = 0x1; m_fs = new DxvkShader(fsInfo, std::move(fsCode)); DxvkSamplerCreateInfo samplerInfo; samplerInfo.magFilter = VK_FILTER_LINEAR; samplerInfo.minFilter = VK_FILTER_LINEAR; samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; samplerInfo.mipmapLodBias = 0.0f; samplerInfo.mipmapLodMin = 0.0f; samplerInfo.mipmapLodMax = 0.0f; samplerInfo.useAnisotropy = VK_FALSE; samplerInfo.maxAnisotropy = 1.0f; samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samplerInfo.compareToDepth = VK_FALSE; samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; samplerInfo.reductionMode = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE; samplerInfo.borderColor = VkClearColorValue(); samplerInfo.usePixelCoord = VK_FALSE; samplerInfo.nonSeamless = VK_FALSE; m_sampler = Device->createSampler(samplerInfo); DxvkBufferCreateInfo bufferInfo; bufferInfo.size = sizeof(UboData); bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; bufferInfo.stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; bufferInfo.access = VK_ACCESS_UNIFORM_READ_BIT; m_ubo = Device->createBuffer(bufferInfo, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); } D3D11VideoContext::~D3D11VideoContext() { } ULONG STDMETHODCALLTYPE D3D11VideoContext::AddRef() { return m_ctx->AddRef(); } ULONG STDMETHODCALLTYPE D3D11VideoContext::Release() { return m_ctx->Release(); } HRESULT STDMETHODCALLTYPE D3D11VideoContext::QueryInterface( REFIID riid, void** ppvObject) { return m_ctx->QueryInterface(riid, ppvObject); } HRESULT STDMETHODCALLTYPE D3D11VideoContext::GetPrivateData( REFGUID Name, UINT* pDataSize, void* pData) { return m_ctx->GetPrivateData(Name, pDataSize, pData); } HRESULT STDMETHODCALLTYPE D3D11VideoContext::SetPrivateData( REFGUID Name, UINT DataSize, const void* pData) { return m_ctx->SetPrivateData(Name, DataSize, pData); } HRESULT STDMETHODCALLTYPE D3D11VideoContext::SetPrivateDataInterface( REFGUID Name, const IUnknown* pUnknown) { return m_ctx->SetPrivateDataInterface(Name, pUnknown); } void STDMETHODCALLTYPE D3D11VideoContext::GetDevice( ID3D11Device** ppDevice) { return m_ctx->GetDevice(ppDevice); } HRESULT STDMETHODCALLTYPE D3D11VideoContext::GetDecoderBuffer( ID3D11VideoDecoder* pDecoder, D3D11_VIDEO_DECODER_BUFFER_TYPE Type, UINT* BufferSize, void** ppBuffer) { Logger::err("D3D11VideoContext::GetDecoderBuffer: Stub"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE D3D11VideoContext::ReleaseDecoderBuffer( ID3D11VideoDecoder* pDecoder, D3D11_VIDEO_DECODER_BUFFER_TYPE Type) { Logger::err("D3D11VideoContext::ReleaseDecoderBuffer: Stub"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE D3D11VideoContext::DecoderBeginFrame( ID3D11VideoDecoder* pDecoder, ID3D11VideoDecoderOutputView* pView, UINT KeySize, const void* pKey) { Logger::err("D3D11VideoContext::DecoderBeginFrame: Stub"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE D3D11VideoContext::DecoderEndFrame( ID3D11VideoDecoder* pDecoder) { Logger::err("D3D11VideoContext::DecoderEndFrame: Stub"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE D3D11VideoContext::SubmitDecoderBuffers( ID3D11VideoDecoder* pDecoder, UINT BufferCount, const D3D11_VIDEO_DECODER_BUFFER_DESC* pBufferDescs) { Logger::err("D3D11VideoContext::SubmitDecoderBuffers: Stub"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE D3D11VideoContext::DecoderExtension( ID3D11VideoDecoder* pDecoder, const D3D11_VIDEO_DECODER_EXTENSION* pExtension) { Logger::err("D3D11VideoContext::DecoderExtension: Stub"); return E_NOTIMPL; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputTargetRect( ID3D11VideoProcessor* pVideoProcessor, BOOL Enable, const RECT* pRect) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetState(); state->outputTargetRectEnabled = Enable; if (Enable) state->outputTargetRect = *pRect; static bool errorShown = false; if (!std::exchange(errorShown, true)) Logger::err("D3D11VideoContext::VideoProcessorSetOutputTargetRect: Stub."); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputBackgroundColor( ID3D11VideoProcessor* pVideoProcessor, BOOL YCbCr, const D3D11_VIDEO_COLOR* pColor) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetState(); state->outputBackgroundColorIsYCbCr = YCbCr; state->outputBackgroundColor = *pColor; static bool errorShown = false; if (!std::exchange(errorShown, true)) Logger::err("D3D11VideoContext::VideoProcessorSetOutputBackgroundColor: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputColorSpace( ID3D11VideoProcessor* pVideoProcessor, const D3D11_VIDEO_PROCESSOR_COLOR_SPACE *pColorSpace) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetState(); state->outputColorSpace = *pColorSpace; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputAlphaFillMode( ID3D11VideoProcessor* pVideoProcessor, D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE AlphaFillMode, UINT StreamIndex) { Logger::err("D3D11VideoContext::VideoProcessorSetOutputAlphaFillMode: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputConstriction( ID3D11VideoProcessor* pVideoProcessor, BOOL Enable, SIZE Size) { Logger::err("D3D11VideoContext::VideoProcessorSetOutputConstriction: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputStereoMode( ID3D11VideoProcessor* pVideoProcessor, BOOL Enable) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetState(); state->outputStereoModeEnabled = Enable; if (Enable) Logger::err("D3D11VideoContext: Stereo output not supported"); } HRESULT STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputExtension( ID3D11VideoProcessor* pVideoProcessor, const GUID* pExtensionGuid, UINT DataSize, void* pData) { Logger::err("D3D11VideoContext::VideoProcessorSetOutputExtension: Stub"); return E_NOTIMPL; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamFrameFormat( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, D3D11_VIDEO_FRAME_FORMAT Format) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); if (!state) return; state->frameFormat = Format; if (Format != D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE) Logger::err(str::format("D3D11VideoContext: Unsupported frame format: ", Format)); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamColorSpace( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, const D3D11_VIDEO_PROCESSOR_COLOR_SPACE *pColorSpace) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); if (!state) return; state->colorSpace = *pColorSpace; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamOutputRate( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, D3D11_VIDEO_PROCESSOR_OUTPUT_RATE Rate, BOOL Repeat, const DXGI_RATIONAL* CustomRate) { Logger::err("D3D11VideoContext::VideoProcessorSetStreamOutputRate: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamSourceRect( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL Enable, const RECT* pRect) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); if (!state) return; state->srcRectEnabled = Enable; if (Enable) state->srcRect = *pRect; static bool errorShown = false; if (!std::exchange(errorShown, true)) Logger::err("D3D11VideoContext::VideoProcessorSetStreamSourceRect: Stub."); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamDestRect( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL Enable, const RECT* pRect) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); if (!state) return; state->dstRectEnabled = Enable; if (Enable) state->dstRect = *pRect; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamAlpha( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL Enable, FLOAT Alpha) { Logger::err("D3D11VideoContext::VideoProcessorSetStreamAlpha: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamPalette( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, UINT EntryCount, const UINT* pEntries) { Logger::err("D3D11VideoContext::VideoProcessorSetStreamPalette: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamPixelAspectRatio( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL Enable, const DXGI_RATIONAL* pSrcAspectRatio, const DXGI_RATIONAL* pDstAspectRatio) { Logger::err("D3D11VideoContext::VideoProcessorSetStreamPixelAspectRatio: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamLumaKey( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL Enable, FLOAT Lower, FLOAT Upper) { Logger::err("D3D11VideoContext::VideoProcessorSetStreamLumaKey: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamStereoFormat( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL Enable, D3D11_VIDEO_PROCESSOR_STEREO_FORMAT Format, BOOL LeftViewFrame0, BOOL BaseViewFrame0, D3D11_VIDEO_PROCESSOR_STEREO_FLIP_MODE FlipMode, int MonoOffset) { Logger::err("D3D11VideoContext::VideoProcessorSetStreamStereoFormat: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamAutoProcessingMode( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL Enable) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); if (!state) return; state->autoProcessingEnabled = Enable; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamFilter( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, D3D11_VIDEO_PROCESSOR_FILTER Filter, BOOL Enable, int Level) { Logger::err("D3D11VideoContext::VideoProcessorSetStreamFilter: Stub"); } HRESULT STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamExtension( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, const GUID* pExtensionGuid, UINT DataSize, void* pData) { Logger::err("D3D11VideoContext::VideoProcessorSetStreamExtension: Stub"); return E_NOTIMPL; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetStreamRotation( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL Enable, D3D11_VIDEO_PROCESSOR_ROTATION Rotation) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); if (!state) return; state->rotationEnabled = Enable; state->rotation = Rotation; if (Enable && Rotation != D3D11_VIDEO_PROCESSOR_ROTATION_IDENTITY) Logger::err(str::format("D3D11VideoContext: Unsupported rotation: ", Rotation)); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputTargetRect( ID3D11VideoProcessor* pVideoProcessor, BOOL* pEnabled, RECT* pRect) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetState(); if (pEnabled) *pEnabled = state->outputTargetRectEnabled; if (pRect) *pRect = state->outputTargetRect; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputBackgroundColor( ID3D11VideoProcessor* pVideoProcessor, BOOL* pYCbCr, D3D11_VIDEO_COLOR* pColor) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetState(); if (pYCbCr) *pYCbCr = state->outputBackgroundColorIsYCbCr; if (pColor) *pColor = state->outputBackgroundColor; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputColorSpace( ID3D11VideoProcessor* pVideoProcessor, D3D11_VIDEO_PROCESSOR_COLOR_SPACE* pColorSpace) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetState(); if (pColorSpace) *pColorSpace = state->outputColorSpace; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputAlphaFillMode( ID3D11VideoProcessor* pVideoProcessor, D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE* pAlphaFillMode, UINT* pStreamIndex) { Logger::err("D3D11VideoContext::VideoProcessorGetOutputAlphaFillMode: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputConstriction( ID3D11VideoProcessor* pVideoProcessor, BOOL* pEnabled, SIZE* pSize) { Logger::err("D3D11VideoContext::VideoProcessorGetOutputConstriction: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputStereoMode( ID3D11VideoProcessor* pVideoProcessor, BOOL* pEnabled) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetState(); if (pEnabled) *pEnabled = state->outputStereoModeEnabled; } HRESULT STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputExtension( ID3D11VideoProcessor* pVideoProcessor, const GUID* pExtensionGuid, UINT DataSize, void* pData) { Logger::err("D3D11VideoContext::VideoProcessorGetOutputExtension: Stub"); return E_NOTIMPL; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamFrameFormat( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, D3D11_VIDEO_FRAME_FORMAT* pFormat) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); if (!state) return; if (pFormat) *pFormat = state->frameFormat; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamColorSpace( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, D3D11_VIDEO_PROCESSOR_COLOR_SPACE* pColorSpace) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); if (!state) return; if (pColorSpace) *pColorSpace = state->colorSpace; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamOutputRate( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, D3D11_VIDEO_PROCESSOR_OUTPUT_RATE* pRate, BOOL* pRepeat, DXGI_RATIONAL* pCustomRate) { Logger::err("D3D11VideoContext::VideoProcessorGetStreamOutputRate: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamSourceRect( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL* pEnabled, RECT* pRect) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); if (!state) return; if (pEnabled) *pEnabled = state->srcRectEnabled; if (pRect) *pRect = state->srcRect; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamDestRect( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL* pEnabled, RECT* pRect) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); if (!state) return; if (pEnabled) *pEnabled = state->dstRectEnabled; if (pRect) *pRect = state->dstRect; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamAlpha( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL* pEnabled, FLOAT* pAlpha) { Logger::err("D3D11VideoContext::VideoProcessorGetStreamAlpha: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamPalette( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, UINT EntryCount, UINT* pEntries) { Logger::err("D3D11VideoContext::VideoProcessorGetStreamPalette: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamPixelAspectRatio( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL* pEnabled, DXGI_RATIONAL* pSrcAspectRatio, DXGI_RATIONAL* pDstAspectRatio) { Logger::err("D3D11VideoContext::VideoProcessorGetStreamPixelAspectRatio: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamLumaKey( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL* pEnabled, FLOAT* pLower, FLOAT* pUpper) { Logger::err("D3D11VideoContext::VideoProcessorGetStreamLumaKey: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamStereoFormat( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL* pEnabled, D3D11_VIDEO_PROCESSOR_STEREO_FORMAT* pFormat, BOOL* pLeftViewFrame0, BOOL* pBaseViewFrame0, D3D11_VIDEO_PROCESSOR_STEREO_FLIP_MODE* pFlipMode, int* pMonoOffset) { Logger::err("D3D11VideoContext::VideoProcessorGetStreamStereoFormat: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamAutoProcessingMode( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL* pEnabled) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); if (!state) return; *pEnabled = state->autoProcessingEnabled; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamFilter( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, D3D11_VIDEO_PROCESSOR_FILTER Filter, BOOL* pEnabled, int* pLevel) { Logger::err("D3D11VideoContext::VideoProcessorGetStreamFilter: Stub"); } HRESULT STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamExtension( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, const GUID* pExtensionGuid, UINT DataSize, void* pData) { Logger::err("D3D11VideoContext::VideoProcessorGetStreamExtension: Stub"); return E_NOTIMPL; } void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetStreamRotation( ID3D11VideoProcessor* pVideoProcessor, UINT StreamIndex, BOOL* pEnable, D3D11_VIDEO_PROCESSOR_ROTATION* pRotation) { D3D10DeviceLock lock = m_ctx->LockContext(); auto state = static_cast(pVideoProcessor)->GetStreamState(StreamIndex); if (!state) return; if (pEnable) *pEnable = state->rotationEnabled; if (pRotation) *pRotation = state->rotation; } HRESULT STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorBlt( ID3D11VideoProcessor* pVideoProcessor, ID3D11VideoProcessorOutputView* pOutputView, UINT FrameIdx, UINT StreamCount, const D3D11_VIDEO_PROCESSOR_STREAM* pStreams) { D3D10DeviceLock lock = m_ctx->LockContext(); auto videoProcessor = static_cast(pVideoProcessor); bool hasStreamsEnabled = false; // Resetting and restoring all context state incurs // a lot of overhead, so only do it as necessary for (uint32_t i = 0; i < StreamCount; i++) { auto streamState = videoProcessor->GetStreamState(i); if (!pStreams[i].Enable || !streamState) continue; if (!hasStreamsEnabled) { m_ctx->ResetCommandListState(); BindOutputView(pOutputView); hasStreamsEnabled = true; } BlitStream(streamState, &pStreams[i]); } if (hasStreamsEnabled) { UnbindResources(); m_ctx->RestoreCommandListState(); } return S_OK; } HRESULT STDMETHODCALLTYPE D3D11VideoContext::NegotiateCryptoSessionKeyExchange( ID3D11CryptoSession* pSession, UINT DataSize, void* pData) { Logger::err("D3D11VideoContext::NegotiateCryptoSessionKeyExchange: Stub"); return E_NOTIMPL; } void STDMETHODCALLTYPE D3D11VideoContext::EncryptionBlt( ID3D11CryptoSession* pSession, ID3D11Texture2D* pSrcSurface, ID3D11Texture2D* pDstSurface, UINT IVSize, void* pIV) { Logger::err("D3D11VideoContext::EncryptionBlt: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::DecryptionBlt( ID3D11CryptoSession* pSession, ID3D11Texture2D* pSrcSurface, ID3D11Texture2D* pDstSurface, D3D11_ENCRYPTED_BLOCK_INFO* pBlockInfo, UINT KeySize, const void* pKey, UINT IVSize, void* pIV) { Logger::err("D3D11VideoContext::DecryptionBlt: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::StartSessionKeyRefresh( ID3D11CryptoSession* pSession, UINT RandomNumberSize, void* pRandomNumber) { Logger::err("D3D11VideoContext::StartSessionKeyRefresh: Stub"); } void STDMETHODCALLTYPE D3D11VideoContext::FinishSessionKeyRefresh( ID3D11CryptoSession* pSession) { Logger::err("D3D11VideoContext::FinishSessionKeyRefresh: Stub"); } HRESULT STDMETHODCALLTYPE D3D11VideoContext::GetEncryptionBltKey( ID3D11CryptoSession* pSession, UINT KeySize, void* pKey) { Logger::err("D3D11VideoContext::GetEncryptionBltKey: Stub"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE D3D11VideoContext::NegotiateAuthenticatedChannelKeyExchange( ID3D11AuthenticatedChannel* pChannel, UINT DataSize, void* pData) { Logger::err("D3D11VideoContext::NegotiateAuthenticatedChannelKeyExchange: Stub"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE D3D11VideoContext::QueryAuthenticatedChannel( ID3D11AuthenticatedChannel* pChannel, UINT InputSize, const void* pInput, UINT OutputSize, void* pOutput) { Logger::err("D3D11VideoContext::QueryAuthenticatedChannel: Stub"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE D3D11VideoContext::ConfigureAuthenticatedChannel( ID3D11AuthenticatedChannel* pChannel, UINT InputSize, const void* pInput, D3D11_AUTHENTICATED_CONFIGURE_OUTPUT* pOutput) { Logger::err("D3D11VideoContext::ConfigureAuthenticatedChannel: Stub"); return E_NOTIMPL; } void D3D11VideoContext::ApplyColorMatrix(float pDst[3][4], const float pSrc[3][4]) { float result[3][4]; for (uint32_t i = 0; i < 3; i++) { for (uint32_t j = 0; j < 4; j++) { result[i][j] = pSrc[i][0] * pDst[0][j] + pSrc[i][1] * pDst[1][j] + pSrc[i][2] * pDst[2][j] + pSrc[i][3] * float(j == 3); } } memcpy(pDst, &result[0][0], sizeof(result)); } void D3D11VideoContext::ApplyYCbCrMatrix(float pColorMatrix[3][4], bool UseBt709) { static const float pretransform[3][4] = { { 0.0f, 1.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f, -0.5f }, { 1.0f, 0.0f, 0.0f, -0.5f }, }; static const float bt601[3][4] = { { 1.0f, 0.000000f, 1.402000f, 0.0f }, { 1.0f, -0.344136f, -0.714136f, 0.0f }, { 1.0f, 1.772000f, 0.000000f, 0.0f }, }; static const float bt709[3][4] = { { 1.0f, 0.000000f, 1.574800f, 0.0f }, { 1.0f, -0.187324f, -0.468124f, 0.0f }, { 1.0f, 1.855600f, 0.000000f, 0.0f }, }; ApplyColorMatrix(pColorMatrix, pretransform); ApplyColorMatrix(pColorMatrix, UseBt709 ? bt709 : bt601); } void D3D11VideoContext::BindOutputView( ID3D11VideoProcessorOutputView* pOutputView) { auto dxvkView = static_cast(pOutputView)->GetView(); m_ctx->EmitCs([this, cView = dxvkView] (DxvkContext* ctx) { DxvkRenderTargets rt; rt.color[0].view = cView; rt.color[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; ctx->bindRenderTargets(std::move(rt), 0u); ctx->bindShader(Rc(m_vs)); ctx->bindShader(Rc(m_fs)); ctx->bindResourceBuffer(VK_SHADER_STAGE_FRAGMENT_BIT, 0, DxvkBufferSlice(m_ubo)); DxvkInputAssemblyState iaState; iaState.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; iaState.primitiveRestart = VK_FALSE; iaState.patchVertexCount = 0; ctx->setInputAssemblyState(iaState); }); VkExtent3D viewExtent = dxvkView->mipLevelExtent(0); m_dstExtent = { viewExtent.width, viewExtent.height }; } void D3D11VideoContext::BlitStream( const D3D11VideoProcessorStreamState* pStreamState, const D3D11_VIDEO_PROCESSOR_STREAM* pStream) { if (pStream->PastFrames || pStream->FutureFrames) Logger::err("D3D11VideoContext: Ignoring non-zero PastFrames and FutureFrames"); if (pStream->OutputIndex) Logger::err("D3D11VideoContext: Ignoring non-zero OutputIndex"); if (pStream->InputFrameOrField) Logger::err("D3D11VideoContext: Ignoring non-zero InputFrameOrField"); auto view = static_cast(pStream->pInputSurface); if (view->NeedsCopy()) { m_ctx->EmitCs([ cDstImage = view->GetShadowCopy(), cSrcImage = view->GetImage(), cSrcLayers = view->GetImageSubresources() ] (DxvkContext* ctx) { VkImageSubresourceLayers cDstLayers; cDstLayers.aspectMask = cSrcLayers.aspectMask; cDstLayers.baseArrayLayer = 0; cDstLayers.layerCount = cSrcLayers.layerCount; cDstLayers.mipLevel = cSrcLayers.mipLevel; ctx->copyImage( cDstImage, cDstLayers, VkOffset3D(), cSrcImage, cSrcLayers, VkOffset3D(), cDstImage->info().extent); }); } m_ctx->EmitCs([this, cStreamState = *pStreamState, cViews = view->GetViews(), cIsYCbCr = view->IsYCbCr() ] (DxvkContext* ctx) { VkViewport viewport; viewport.x = 0.0f; viewport.y = 0.0f; viewport.width = float(m_dstExtent.width); viewport.height = float(m_dstExtent.height); viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; VkRect2D scissor; scissor.offset = { 0, 0 }; scissor.extent = m_dstExtent; if (cStreamState.dstRectEnabled) { viewport.x = float(cStreamState.dstRect.left); viewport.y = float(cStreamState.dstRect.top); viewport.width = float(cStreamState.dstRect.right) - viewport.x; viewport.height = float(cStreamState.dstRect.bottom) - viewport.y; } UboData uboData = { }; uboData.colorMatrix[0][0] = 1.0f; uboData.colorMatrix[1][1] = 1.0f; uboData.colorMatrix[2][2] = 1.0f; uboData.coordMatrix[0][0] = 1.0f; uboData.coordMatrix[1][1] = 1.0f; uboData.yMin = 0.0f; uboData.yMax = 1.0f; uboData.isPlanar = cViews[1] != nullptr; if (cIsYCbCr) ApplyYCbCrMatrix(uboData.colorMatrix, cStreamState.colorSpace.YCbCr_Matrix); if (cStreamState.colorSpace.Nominal_Range) { uboData.yMin = 0.0627451f; uboData.yMax = 0.9215686f; } DxvkBufferSliceHandle uboSlice = m_ubo->allocSlice(); memcpy(uboSlice.mapPtr, &uboData, sizeof(uboData)); ctx->invalidateBuffer(m_ubo, uboSlice); ctx->setViewports(1, &viewport, &scissor); ctx->bindResourceSampler(VK_SHADER_STAGE_FRAGMENT_BIT, 1, Rc(m_sampler)); for (uint32_t i = 0; i < cViews.size(); i++) ctx->bindResourceImageView(VK_SHADER_STAGE_FRAGMENT_BIT, 2 + i, Rc(cViews[i])); ctx->draw(3, 1, 0, 0); ctx->bindResourceSampler(VK_SHADER_STAGE_FRAGMENT_BIT, 1, nullptr); for (uint32_t i = 0; i < cViews.size(); i++) ctx->bindResourceImageView(VK_SHADER_STAGE_FRAGMENT_BIT, 2 + i, nullptr); }); } void D3D11VideoContext::UnbindResources() { m_ctx->EmitCs([] (DxvkContext* ctx) { ctx->bindRenderTargets(DxvkRenderTargets(), 0u); ctx->bindShader(nullptr); ctx->bindShader(nullptr); ctx->bindResourceBuffer(VK_SHADER_STAGE_FRAGMENT_BIT, 0, DxvkBufferSlice()); }); } }