mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-14 04:29:15 +01:00
[d3d11] Implement basic video processor blitting
This commit is contained in:
parent
969ac59667
commit
e87aa08fd2
@ -14,7 +14,7 @@ namespace dxvk {
|
||||
const Rc<DxvkDevice>& Device)
|
||||
: D3D11DeviceContext(pParent, Device, DxvkCsChunkFlag::SingleUse),
|
||||
m_csThread(Device->createContext()),
|
||||
m_videoContext(this) {
|
||||
m_videoContext(this, Device) {
|
||||
EmitCs([
|
||||
cDevice = m_device,
|
||||
cRelaxedBarriers = pParent->GetOptions()->relaxedBarriers
|
||||
|
@ -15,6 +15,7 @@ namespace dxvk {
|
||||
|
||||
class D3D11ImmediateContext : public D3D11DeviceContext {
|
||||
friend class D3D11SwapChain;
|
||||
friend class D3D11VideoContext;
|
||||
public:
|
||||
|
||||
D3D11ImmediateContext(
|
||||
|
@ -4,6 +4,9 @@
|
||||
#include "d3d11_context_imm.h"
|
||||
#include "d3d11_video.h"
|
||||
|
||||
#include <d3d11_video_blit_frag.h>
|
||||
#include <d3d11_video_blit_vert.h>
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
D3D11VideoProcessorEnumerator::D3D11VideoProcessorEnumerator(
|
||||
@ -302,9 +305,55 @@ namespace dxvk {
|
||||
|
||||
|
||||
D3D11VideoContext::D3D11VideoContext(
|
||||
D3D11ImmediateContext* pContext)
|
||||
D3D11ImmediateContext* pContext,
|
||||
const Rc<DxvkDevice>& Device)
|
||||
: m_ctx(pContext) {
|
||||
const SpirvCodeBuffer vsCode(d3d11_video_blit_vert);
|
||||
const SpirvCodeBuffer fsCode(d3d11_video_blit_frag);
|
||||
|
||||
const std::array<DxvkResourceSlot, 4> fsResourceSlots = {{
|
||||
{ 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_IMAGE_VIEW_TYPE_2D },
|
||||
{ 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_IMAGE_VIEW_TYPE_2D },
|
||||
}};
|
||||
|
||||
m_vs = Device->createShader(
|
||||
VK_SHADER_STAGE_VERTEX_BIT,
|
||||
0, nullptr, { 0u, 1u },
|
||||
vsCode);
|
||||
|
||||
m_fs = Device->createShader(
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
fsResourceSlots.size(),
|
||||
fsResourceSlots.data(),
|
||||
{ 1u, 1u, 0u, 0u },
|
||||
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.borderColor = VkClearColorValue();
|
||||
samplerInfo.usePixelCoord = 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);
|
||||
}
|
||||
|
||||
|
||||
@ -414,7 +463,16 @@ namespace dxvk {
|
||||
ID3D11VideoProcessor* pVideoProcessor,
|
||||
BOOL Enable,
|
||||
const RECT* pRect) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorSetOutputTargetRect: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetState();
|
||||
state->outputTargetRectEnabled = Enable;
|
||||
|
||||
if (Enable)
|
||||
state->outputTargetRect = *pRect;
|
||||
|
||||
static bool errorShown = false;
|
||||
|
||||
if (!std::exchange(errorShown, true))
|
||||
Logger::err("D3D11VideoContext::VideoProcessorSetOutputTargetRect: Stub.");
|
||||
}
|
||||
|
||||
|
||||
@ -422,14 +480,22 @@ namespace dxvk {
|
||||
ID3D11VideoProcessor* pVideoProcessor,
|
||||
BOOL YCbCr,
|
||||
const D3D11_VIDEO_COLOR* pColor) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorSetOutputBackgroundColor: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(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) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorSetOutputColorSpace: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetState();
|
||||
state->outputColorSpace = *pColorSpace;
|
||||
}
|
||||
|
||||
|
||||
@ -452,7 +518,11 @@ namespace dxvk {
|
||||
void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorSetOutputStereoMode(
|
||||
ID3D11VideoProcessor* pVideoProcessor,
|
||||
BOOL Enable) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorSetOutputStereoMode: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetState();
|
||||
state->outputStereoModeEnabled = Enable;
|
||||
|
||||
if (Enable)
|
||||
Logger::err("D3D11VideoContext: Stereo output not supported");
|
||||
}
|
||||
|
||||
|
||||
@ -470,7 +540,15 @@ namespace dxvk {
|
||||
ID3D11VideoProcessor* pVideoProcessor,
|
||||
UINT StreamIndex,
|
||||
D3D11_VIDEO_FRAME_FORMAT Format) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorSetStreamFrameFormat: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(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));
|
||||
}
|
||||
|
||||
|
||||
@ -478,7 +556,12 @@ namespace dxvk {
|
||||
ID3D11VideoProcessor* pVideoProcessor,
|
||||
UINT StreamIndex,
|
||||
const D3D11_VIDEO_PROCESSOR_COLOR_SPACE *pColorSpace) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorSetStreamColorSpace: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
|
||||
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
state->colorSpace = *pColorSpace;
|
||||
}
|
||||
|
||||
|
||||
@ -497,7 +580,20 @@ namespace dxvk {
|
||||
UINT StreamIndex,
|
||||
BOOL Enable,
|
||||
const RECT* pRect) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorSetStreamSourceRect: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(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.");
|
||||
}
|
||||
|
||||
|
||||
@ -506,7 +602,15 @@ namespace dxvk {
|
||||
UINT StreamIndex,
|
||||
BOOL Enable,
|
||||
const RECT* pRect) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorSetStreamDestRect: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
|
||||
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
state->dstRectEnabled = Enable;
|
||||
|
||||
if (Enable)
|
||||
state->dstRect = *pRect;
|
||||
}
|
||||
|
||||
|
||||
@ -565,7 +669,12 @@ namespace dxvk {
|
||||
ID3D11VideoProcessor* pVideoProcessor,
|
||||
UINT StreamIndex,
|
||||
BOOL Enable) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorSetStreamAutoProcessingMode: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
|
||||
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
state->autoProcessingEnabled = Enable;
|
||||
}
|
||||
|
||||
|
||||
@ -595,7 +704,16 @@ namespace dxvk {
|
||||
UINT StreamIndex,
|
||||
BOOL Enable,
|
||||
D3D11_VIDEO_PROCESSOR_ROTATION Rotation) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorSetStreamRotation: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(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));
|
||||
}
|
||||
|
||||
|
||||
@ -603,7 +721,13 @@ namespace dxvk {
|
||||
ID3D11VideoProcessor* pVideoProcessor,
|
||||
BOOL* pEnabled,
|
||||
RECT* pRect) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorGetOutputTargetRect: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetState();
|
||||
|
||||
if (pEnabled)
|
||||
*pEnabled = state->outputTargetRectEnabled;
|
||||
|
||||
if (pRect)
|
||||
*pRect = state->outputTargetRect;
|
||||
}
|
||||
|
||||
|
||||
@ -611,14 +735,23 @@ namespace dxvk {
|
||||
ID3D11VideoProcessor* pVideoProcessor,
|
||||
BOOL* pYCbCr,
|
||||
D3D11_VIDEO_COLOR* pColor) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorGetOutputBackgroundColor: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetState();
|
||||
|
||||
if (pYCbCr)
|
||||
*pYCbCr = state->outputBackgroundColorIsYCbCr;
|
||||
|
||||
if (pColor)
|
||||
*pColor = state->outputBackgroundColor;
|
||||
}
|
||||
|
||||
|
||||
void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputColorSpace(
|
||||
ID3D11VideoProcessor* pVideoProcessor,
|
||||
D3D11_VIDEO_PROCESSOR_COLOR_SPACE* pColorSpace) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorGetOutputColorSpace: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetState();
|
||||
|
||||
if (pColorSpace)
|
||||
*pColorSpace = state->outputColorSpace;
|
||||
}
|
||||
|
||||
|
||||
@ -641,7 +774,10 @@ namespace dxvk {
|
||||
void STDMETHODCALLTYPE D3D11VideoContext::VideoProcessorGetOutputStereoMode(
|
||||
ID3D11VideoProcessor* pVideoProcessor,
|
||||
BOOL* pEnabled) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorGetOutputStereoMode: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetState();
|
||||
|
||||
if (pEnabled)
|
||||
*pEnabled = state->outputStereoModeEnabled;
|
||||
}
|
||||
|
||||
|
||||
@ -659,7 +795,13 @@ namespace dxvk {
|
||||
ID3D11VideoProcessor* pVideoProcessor,
|
||||
UINT StreamIndex,
|
||||
D3D11_VIDEO_FRAME_FORMAT* pFormat) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorGetStreamFrameFormat: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
|
||||
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
if (pFormat)
|
||||
*pFormat = state->frameFormat;
|
||||
}
|
||||
|
||||
|
||||
@ -667,7 +809,13 @@ namespace dxvk {
|
||||
ID3D11VideoProcessor* pVideoProcessor,
|
||||
UINT StreamIndex,
|
||||
D3D11_VIDEO_PROCESSOR_COLOR_SPACE* pColorSpace) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorGetStreamColorSpace: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
|
||||
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
if (pColorSpace)
|
||||
*pColorSpace = state->colorSpace;
|
||||
}
|
||||
|
||||
|
||||
@ -686,7 +834,16 @@ namespace dxvk {
|
||||
UINT StreamIndex,
|
||||
BOOL* pEnabled,
|
||||
RECT* pRect) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorGetStreamSourceRect: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
|
||||
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
if (pEnabled)
|
||||
*pEnabled = state->srcRectEnabled;
|
||||
|
||||
if (pRect)
|
||||
*pRect = state->srcRect;
|
||||
}
|
||||
|
||||
|
||||
@ -695,7 +852,16 @@ namespace dxvk {
|
||||
UINT StreamIndex,
|
||||
BOOL* pEnabled,
|
||||
RECT* pRect) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorGetStreamDestRect: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
|
||||
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
if (pEnabled)
|
||||
*pEnabled = state->dstRectEnabled;
|
||||
|
||||
if (pRect)
|
||||
*pRect = state->dstRect;
|
||||
}
|
||||
|
||||
|
||||
@ -754,7 +920,12 @@ namespace dxvk {
|
||||
ID3D11VideoProcessor* pVideoProcessor,
|
||||
UINT StreamIndex,
|
||||
BOOL* pEnabled) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorGetStreamAutoProcessingMode: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
|
||||
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
*pEnabled = state->autoProcessingEnabled;
|
||||
}
|
||||
|
||||
|
||||
@ -784,7 +955,16 @@ namespace dxvk {
|
||||
UINT StreamIndex,
|
||||
BOOL* pEnable,
|
||||
D3D11_VIDEO_PROCESSOR_ROTATION* pRotation) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorGetStreamRotation: Stub");
|
||||
auto state = static_cast<D3D11VideoProcessor*>(pVideoProcessor)->GetStreamState(StreamIndex);
|
||||
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
if (pEnable)
|
||||
*pEnable = state->rotationEnabled;
|
||||
|
||||
if (pRotation)
|
||||
*pRotation = state->rotation;
|
||||
}
|
||||
|
||||
|
||||
@ -794,8 +974,30 @@ namespace dxvk {
|
||||
UINT FrameIdx,
|
||||
UINT StreamCount,
|
||||
const D3D11_VIDEO_PROCESSOR_STREAM* pStreams) {
|
||||
Logger::err("D3D11VideoContext::VideoProcessorBlt: Stub");
|
||||
return E_NOTIMPL;
|
||||
auto videoProcessor = static_cast<D3D11VideoProcessor*>(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->ResetState();
|
||||
BindOutputView(pOutputView);
|
||||
hasStreamsEnabled = true;
|
||||
}
|
||||
|
||||
BlitStream(streamState, &pStreams[i]);
|
||||
}
|
||||
|
||||
if (hasStreamsEnabled)
|
||||
m_ctx->RestoreState();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -883,4 +1085,140 @@ namespace dxvk {
|
||||
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<D3D11VideoProcessorOutputView*>(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(rt);
|
||||
ctx->bindShader(VK_SHADER_STAGE_VERTEX_BIT, m_vs);
|
||||
ctx->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_fs);
|
||||
ctx->bindResourceBuffer(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<D3D11VideoProcessorInputView*>(pStream->pInputSurface);
|
||||
|
||||
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;
|
||||
|
||||
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(1, m_sampler);
|
||||
|
||||
for (uint32_t i = 0; i < cViews.size(); i++)
|
||||
ctx->bindResourceView(2 + i, cViews[i], nullptr);
|
||||
|
||||
ctx->draw(3, 1, 0, 0);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
static constexpr uint32_t D3D11_VK_VIDEO_STREAM_COUNT = 8;
|
||||
|
||||
class D3D11VideoProcessorEnumerator : public D3D11DeviceChild<ID3D11VideoProcessorEnumerator> {
|
||||
|
||||
public:
|
||||
@ -48,6 +50,26 @@ namespace dxvk {
|
||||
};
|
||||
|
||||
|
||||
struct D3D11VideoProcessorStreamState {
|
||||
BOOL autoProcessingEnabled = TRUE;
|
||||
BOOL dstRectEnabled = FALSE;
|
||||
BOOL srcRectEnabled = FALSE;
|
||||
BOOL rotationEnabled = FALSE;
|
||||
RECT dstRect = RECT();
|
||||
RECT srcRect = RECT();
|
||||
D3D11_VIDEO_FRAME_FORMAT frameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
|
||||
D3D11_VIDEO_PROCESSOR_ROTATION rotation = D3D11_VIDEO_PROCESSOR_ROTATION_IDENTITY;
|
||||
D3D11_VIDEO_PROCESSOR_COLOR_SPACE colorSpace = D3D11_VIDEO_PROCESSOR_COLOR_SPACE();
|
||||
};
|
||||
|
||||
struct D3D11VideoProcessorState {
|
||||
BOOL outputStereoModeEnabled = FALSE;
|
||||
BOOL outputBackgroundColorIsYCbCr = FALSE;
|
||||
BOOL outputTargetRectEnabled = FALSE;
|
||||
RECT outputTargetRect = RECT();
|
||||
D3D11_VIDEO_COLOR outputBackgroundColor = D3D11_VIDEO_COLOR();
|
||||
D3D11_VIDEO_PROCESSOR_COLOR_SPACE outputColorSpace = D3D11_VIDEO_PROCESSOR_COLOR_SPACE();
|
||||
};
|
||||
|
||||
class D3D11VideoProcessor : public D3D11DeviceChild<ID3D11VideoProcessor> {
|
||||
|
||||
@ -70,10 +92,22 @@ namespace dxvk {
|
||||
void STDMETHODCALLTYPE GetRateConversionCaps(
|
||||
D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS *pCaps);
|
||||
|
||||
D3D11VideoProcessorState* GetState() {
|
||||
return &m_state;
|
||||
}
|
||||
|
||||
D3D11VideoProcessorStreamState* GetStreamState(UINT StreamIndex) {
|
||||
return StreamIndex < D3D11_VK_VIDEO_STREAM_COUNT
|
||||
? &m_streams[StreamIndex]
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
D3D11VideoProcessorEnumerator* m_enumerator;
|
||||
uint32_t m_rateConversionIndex;
|
||||
D3D11VideoProcessorState m_state;
|
||||
D3D11VideoProcessorStreamState m_streams[D3D11_VK_VIDEO_STREAM_COUNT];
|
||||
|
||||
};
|
||||
|
||||
@ -104,6 +138,10 @@ namespace dxvk {
|
||||
return m_isYCbCr;
|
||||
}
|
||||
|
||||
std::array<Rc<DxvkImageView>, 2> GetViews() const {
|
||||
return m_views;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Com<ID3D11Resource> m_resource;
|
||||
@ -138,6 +176,10 @@ namespace dxvk {
|
||||
void STDMETHODCALLTYPE GetDesc(
|
||||
D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* pDesc);
|
||||
|
||||
Rc<DxvkImageView> GetView() const {
|
||||
return m_view;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Com<ID3D11Resource> m_resource;
|
||||
@ -153,7 +195,8 @@ namespace dxvk {
|
||||
public:
|
||||
|
||||
D3D11VideoContext(
|
||||
D3D11ImmediateContext* pContext);
|
||||
D3D11ImmediateContext* pContext,
|
||||
const Rc<DxvkDevice>& Device);
|
||||
|
||||
~D3D11VideoContext();
|
||||
|
||||
@ -520,7 +563,31 @@ namespace dxvk {
|
||||
|
||||
private:
|
||||
|
||||
D3D11ImmediateContext* m_ctx;
|
||||
struct alignas(16) UboData {
|
||||
float colorMatrix[3][4];
|
||||
float coordMatrix[3][2];
|
||||
float yMin, yMax;
|
||||
};
|
||||
|
||||
D3D11ImmediateContext* m_ctx;
|
||||
|
||||
Rc<DxvkSampler> m_sampler;
|
||||
Rc<DxvkShader> m_vs;
|
||||
Rc<DxvkShader> m_fs;
|
||||
Rc<DxvkBuffer> m_ubo;
|
||||
|
||||
VkExtent2D m_dstExtent = { 0u, 0u };
|
||||
|
||||
void ApplyColorMatrix(float pDst[3][4], const float pSrc[3][4]);
|
||||
|
||||
void ApplyYCbCrMatrix(float pColorMatrix[3][4], bool UseBt709);
|
||||
|
||||
void BindOutputView(
|
||||
ID3D11VideoProcessorOutputView* pOutputView);
|
||||
|
||||
void BlitStream(
|
||||
const D3D11VideoProcessorStreamState* pStreamState,
|
||||
const D3D11_VIDEO_PROCESSOR_STREAM* pStream);
|
||||
|
||||
};
|
||||
|
||||
|
@ -59,7 +59,13 @@ d3d11_src = [
|
||||
'd3d11_view_uav.cpp',
|
||||
]
|
||||
|
||||
d3d11_dll = shared_library('d3d11'+dll_ext, dxgi_common_src + d3d11_src + d3d10_src, d3d11_res,
|
||||
d3d11_shaders = files([
|
||||
'shaders/d3d11_video_blit_frag.frag',
|
||||
'shaders/d3d11_video_blit_vert.vert',
|
||||
])
|
||||
|
||||
d3d11_dll = shared_library('d3d11'+dll_ext, dxgi_common_src + d3d11_src + d3d10_src,
|
||||
glsl_generator.process(d3d11_shaders), d3d11_res,
|
||||
name_prefix : '',
|
||||
dependencies : [ lib_dxgi, dxbc_dep, dxvk_dep ],
|
||||
include_directories : dxvk_include_path,
|
||||
|
56
src/d3d11/shaders/d3d11_video_blit_frag.frag
Normal file
56
src/d3d11/shaders/d3d11_video_blit_frag.frag
Normal file
@ -0,0 +1,56 @@
|
||||
#version 450
|
||||
|
||||
layout(constant_id = 3) const bool c_planar = true;
|
||||
|
||||
// Can't use matrix types here since even a two-row
|
||||
// matrix will be padded to 16 bytes per column for
|
||||
// absolutely no reason
|
||||
layout(std140, set = 0, binding = 0)
|
||||
uniform ubo_t {
|
||||
vec4 color_matrix_r1;
|
||||
vec4 color_matrix_r2;
|
||||
vec4 color_matrix_r3;
|
||||
vec2 coord_matrix_c1;
|
||||
vec2 coord_matrix_c2;
|
||||
vec2 coord_matrix_c3;
|
||||
float y_min;
|
||||
float y_max;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec2 i_texcoord;
|
||||
layout(location = 0) out vec4 o_color;
|
||||
|
||||
layout(set = 0, binding = 1) uniform sampler s_sampler;
|
||||
layout(set = 0, binding = 2) uniform texture2D s_inputY;
|
||||
layout(set = 0, binding = 3) uniform texture2D s_inputCbCr;
|
||||
|
||||
void main() {
|
||||
// Transform input texture coordinates to
|
||||
// account for rotation and source rectangle
|
||||
mat3x2 coord_matrix = mat3x2(
|
||||
coord_matrix_c1,
|
||||
coord_matrix_c2,
|
||||
coord_matrix_c3);
|
||||
|
||||
vec2 coord = coord_matrix * vec3(i_texcoord, 1.0f);
|
||||
|
||||
// Fetch source image color
|
||||
vec4 color = vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
if (c_planar) {
|
||||
color.g = texture(sampler2D(s_inputY, s_sampler), coord).r;
|
||||
color.rb = texture(sampler2D(s_inputCbCr, s_sampler), coord).gr;
|
||||
color.g = clamp((color.g - y_min) / (y_max - y_min), 0.0f, 1.0f);
|
||||
} else {
|
||||
color = texture(sampler2D(s_inputY, s_sampler), coord);
|
||||
}
|
||||
|
||||
// Color space transformation
|
||||
mat3x4 color_matrix = mat3x4(
|
||||
color_matrix_r1,
|
||||
color_matrix_r2,
|
||||
color_matrix_r3);
|
||||
|
||||
o_color.rgb = vec4(color.rgb, 1.0f) * color_matrix;
|
||||
o_color.a = color.a;
|
||||
}
|
12
src/d3d11/shaders/d3d11_video_blit_vert.vert
Normal file
12
src/d3d11/shaders/d3d11_video_blit_vert.vert
Normal file
@ -0,0 +1,12 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) out vec2 o_texcoord;
|
||||
|
||||
void main() {
|
||||
vec2 coord = vec2(
|
||||
float(gl_VertexIndex & 1) * 2.0f,
|
||||
float(gl_VertexIndex & 2));
|
||||
|
||||
o_texcoord = coord;
|
||||
gl_Position = vec4(-1.0f + 2.0f * coord, 0.0f, 1.0f);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user