1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-20 10:54:16 +01:00

[d3d9] Remove format conversion context

This commit is contained in:
Philip Rebohle 2024-10-22 12:48:39 +02:00 committed by Philip Rebohle
parent f9a99e81f4
commit b4ed108105
4 changed files with 179 additions and 67 deletions

View File

@ -331,6 +331,7 @@ namespace dxvk {
if (m_mapping.ConversionFormatInfo.FormatType != D3D9ConversionFormat_None) {
imageInfo.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
imageInfo.stages |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
imageInfo.shared = true;
}
DecodeMultiSampleType(m_device->GetDXVKDevice(), m_desc.MultiSample, m_desc.MultisampleQuality, &imageInfo.sampleCount);

View File

@ -5055,13 +5055,17 @@ namespace dxvk {
slice.mapPtr, mapPtr, srcBlockCount, formatElementSize,
pitch, std::min(pSrcTexture->GetPlaneCount(), 2u) * pitch * srcBlockCount.height);
Flush();
SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
EmitCs([this,
cConvertFormat = convertFormat,
cDstImage = std::move(image),
cDstLayers = convertedDstLayers,
cSrcSlice = std::move(slice.slice)
] (DxvkContext* ctx) {
auto contextObjects = ctx->beginExternalRendering();
m_converter->ConvertFormat(
convertFormat,
image, convertedDstLayers,
slice.slice);
m_converter->ConvertFormat(contextObjects,
cConvertFormat, cDstImage, cDstLayers, cSrcSlice);
});
}
UnmapTextures();
ConsiderFlush(GpuFlushType::ImplicitWeakHint);
@ -5848,8 +5852,6 @@ namespace dxvk {
if constexpr (Synchronize9On12)
m_submitStatus.result = VK_NOT_READY;
m_converter->Flush();
// Update signaled staging buffer counter and signal the fence
m_stagingMemorySignaled = m_stagingBuffer.getStatistics().allocatedTotal;

View File

@ -11,21 +11,23 @@
namespace dxvk {
D3D9FormatHelper::D3D9FormatHelper(const Rc<DxvkDevice>& device)
: m_device(device), m_context(m_device->createContext(DxvkContextType::Supplementary)) {
m_context->beginRecording(
m_device->createCommandList());
InitShaders();
: m_device (device)
, m_setLayout (CreateSetLayout())
, m_pipelineLayout (CreatePipelineLayout()) {
InitPipelines();
}
void D3D9FormatHelper::Flush() {
if (m_transferCommands != 0)
FlushInternal();
D3D9FormatHelper::~D3D9FormatHelper() {
auto vk = m_device->vkd();
for (auto& p : m_pipelines)
vk->vkDestroyPipeline(vk->device(), p, nullptr);
}
void D3D9FormatHelper::ConvertFormat(
const DxvkContextObjects& ctx,
D3D9_CONVERSION_FORMAT_INFO conversionFormat,
const Rc<DxvkImage>& dstImage,
VkImageSubresourceLayers dstSubresource,
@ -33,33 +35,32 @@ namespace dxvk {
switch (conversionFormat.FormatType) {
case D3D9ConversionFormat_YUY2:
case D3D9ConversionFormat_UYVY: {
uint32_t specConstant = conversionFormat.FormatType == D3D9ConversionFormat_UYVY ? 1 : 0;
ConvertGenericFormat(conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R32_UINT, specConstant, { 2u, 1u });
ConvertGenericFormat(ctx, conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R32_UINT, { 2u, 1u });
break;
}
case D3D9ConversionFormat_NV12:
ConvertGenericFormat(conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R16_UINT, 0, { 2u, 1u });
ConvertGenericFormat(ctx, conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R16_UINT, { 2u, 1u });
break;
case D3D9ConversionFormat_YV12:
ConvertGenericFormat(conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R8_UINT, 0, { 1u, 1u });
ConvertGenericFormat(ctx, conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R8_UINT, { 1u, 1u });
break;
case D3D9ConversionFormat_L6V5U5:
ConvertGenericFormat(conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R16_UINT, 0, { 1u, 1u });
ConvertGenericFormat(ctx, conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R16_UINT, { 1u, 1u });
break;
case D3D9ConversionFormat_X8L8V8U8:
ConvertGenericFormat(conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R32_UINT, 0, { 1u, 1u });
ConvertGenericFormat(ctx, conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R32_UINT, { 1u, 1u });
break;
case D3D9ConversionFormat_A2W10V10U10:
ConvertGenericFormat(conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R32_UINT, 0, { 1u, 1u });
ConvertGenericFormat(ctx, conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R32_UINT, { 1u, 1u });
break;
case D3D9ConversionFormat_W11V11U10:
ConvertGenericFormat(conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R32_UINT, 0, { 1u, 1u });
ConvertGenericFormat(ctx, conversionFormat, dstImage, dstSubresource, srcSlice, VK_FORMAT_R32_UINT, { 1u, 1u });
break;
default:
@ -69,12 +70,12 @@ namespace dxvk {
void D3D9FormatHelper::ConvertGenericFormat(
const DxvkContextObjects& ctx,
D3D9_CONVERSION_FORMAT_INFO videoFormat,
const Rc<DxvkImage>& dstImage,
VkImageSubresourceLayers dstSubresource,
const DxvkBufferSlice& srcSlice,
VkFormat bufferFormat,
uint32_t specConstantValue,
VkExtent2D macroPixelRun) {
DxvkImageViewKey imageViewInfo;
imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
@ -99,53 +100,156 @@ namespace dxvk {
bufferViewInfo.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
auto tmpBufferView = srcSlice.buffer()->createView(bufferViewInfo);
m_context->setSpecConstant(VK_PIPELINE_BIND_POINT_COMPUTE, 0, specConstantValue);
m_context->bindResourceImageView(VK_SHADER_STAGE_COMPUTE_BIT, BindingIds::Image, std::move(tmpImageView));
m_context->bindResourceBufferView(VK_SHADER_STAGE_COMPUTE_BIT, BindingIds::Buffer, std::move(tmpBufferView));
m_context->bindShader<VK_SHADER_STAGE_COMPUTE_BIT>(Rc<DxvkShader>(m_shaders[videoFormat.FormatType]));
m_context->pushConstants(0, sizeof(VkExtent2D), &imageExtent);
m_context->dispatch(
(imageExtent.width / 8) + (imageExtent.width % 8),
(imageExtent.height / 8) + (imageExtent.height % 8),
1);
VkDescriptorSet set = ctx.descriptorPool->alloc(m_setLayout);
m_transferCommands += 1;
VkDescriptorImageInfo imageDescriptor = { };
imageDescriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
imageDescriptor.imageView = tmpImageView->handle();
VkBufferView bufferViewHandle = tmpBufferView->handle();
std::array<VkWriteDescriptorSet, 2> descriptorWrites = {{
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr,
set, 0, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageDescriptor },
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr,
set, 1, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, nullptr, nullptr, &bufferViewHandle },
}};
ctx.cmd->updateDescriptorSets(
descriptorWrites.size(),
descriptorWrites.data());
ctx.cmd->cmdBindPipeline(DxvkCmdBuffer::ExecBuffer,
VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelines[videoFormat.FormatType]);
ctx.cmd->cmdBindDescriptorSet(DxvkCmdBuffer::ExecBuffer,
VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, set, 0, nullptr);
ctx.cmd->cmdPushConstants(DxvkCmdBuffer::ExecBuffer, m_pipelineLayout,
VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(VkExtent2D), &imageExtent);
ctx.cmd->cmdDispatch(DxvkCmdBuffer::ExecBuffer,
((imageExtent.width + 7u) / 8u),
((imageExtent.height + 7u) / 8u),
1u);
// We can reasonably assume that the image is in GENERAL layout anyway
VkMemoryBarrier2 memoryBarrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER_2 };
memoryBarrier.srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
memoryBarrier.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT;
memoryBarrier.dstStageMask = dstImage->info().stages | srcSlice.buffer()->info().stages;
memoryBarrier.dstAccessMask = dstImage->info().access | srcSlice.buffer()->info().access;
VkDependencyInfo depInfo = { VK_STRUCTURE_TYPE_DEPENDENCY_INFO };
depInfo.memoryBarrierCount = 1u;
depInfo.pMemoryBarriers = &memoryBarrier;
ctx.cmd->cmdPipelineBarrier(DxvkCmdBuffer::ExecBuffer, &depInfo);
ctx.cmd->track(tmpImageView->image(), DxvkAccess::Write);
ctx.cmd->track(tmpBufferView->buffer(), DxvkAccess::Read);
}
void D3D9FormatHelper::InitShaders() {
m_shaders[D3D9ConversionFormat_YUY2] = InitShader(d3d9_convert_yuy2_uyvy);
m_shaders[D3D9ConversionFormat_UYVY] = m_shaders[D3D9ConversionFormat_YUY2];
m_shaders[D3D9ConversionFormat_L6V5U5] = InitShader(d3d9_convert_l6v5u5);
m_shaders[D3D9ConversionFormat_X8L8V8U8] = InitShader(d3d9_convert_x8l8v8u8);
m_shaders[D3D9ConversionFormat_A2W10V10U10] = InitShader(d3d9_convert_a2w10v10u10);
m_shaders[D3D9ConversionFormat_W11V11U10] = InitShader(d3d9_convert_w11v11u10);
m_shaders[D3D9ConversionFormat_NV12] = InitShader(d3d9_convert_nv12);
m_shaders[D3D9ConversionFormat_YV12] = InitShader(d3d9_convert_yv12);
void D3D9FormatHelper::InitPipelines() {
m_pipelines[D3D9ConversionFormat_YUY2] = CreatePipeline(sizeof(d3d9_convert_yuy2_uyvy), d3d9_convert_yuy2_uyvy, 0);
m_pipelines[D3D9ConversionFormat_UYVY] = CreatePipeline(sizeof(d3d9_convert_yuy2_uyvy), d3d9_convert_yuy2_uyvy, 1);
m_pipelines[D3D9ConversionFormat_L6V5U5] = CreatePipeline(sizeof(d3d9_convert_l6v5u5), d3d9_convert_l6v5u5, 0);
m_pipelines[D3D9ConversionFormat_X8L8V8U8] = CreatePipeline(sizeof(d3d9_convert_x8l8v8u8), d3d9_convert_x8l8v8u8, 0);
m_pipelines[D3D9ConversionFormat_A2W10V10U10] = CreatePipeline(sizeof(d3d9_convert_a2w10v10u10), d3d9_convert_a2w10v10u10, 0);
m_pipelines[D3D9ConversionFormat_W11V11U10] = CreatePipeline(sizeof(d3d9_convert_w11v11u10), d3d9_convert_w11v11u10, 0);
m_pipelines[D3D9ConversionFormat_NV12] = CreatePipeline(sizeof(d3d9_convert_nv12), d3d9_convert_nv12, 0);
m_pipelines[D3D9ConversionFormat_YV12] = CreatePipeline(sizeof(d3d9_convert_yv12), d3d9_convert_yv12, 0);
}
Rc<DxvkShader> D3D9FormatHelper::InitShader(SpirvCodeBuffer code) {
const std::array<DxvkBindingInfo, 2> bindings = { {
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, BindingIds::Image, VK_IMAGE_VIEW_TYPE_2D, VK_SHADER_STAGE_COMPUTE_BIT, VK_ACCESS_SHADER_WRITE_BIT },
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, BindingIds::Buffer, VK_IMAGE_VIEW_TYPE_1D, VK_SHADER_STAGE_COMPUTE_BIT, VK_ACCESS_SHADER_READ_BIT },
} };
VkDescriptorSetLayout D3D9FormatHelper::CreateSetLayout() {
auto vk = m_device->vkd();
DxvkShaderCreateInfo info;
info.stage = VK_SHADER_STAGE_COMPUTE_BIT;
static const std::array<VkDescriptorSetLayoutBinding, 2> bindings = {{
{ 0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT },
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT },
}};
VkDescriptorSetLayoutCreateInfo info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
info.bindingCount = bindings.size();
info.bindings = bindings.data();
info.pushConstStages = VK_SHADER_STAGE_COMPUTE_BIT;
info.pushConstSize = sizeof(VkExtent2D);
info.pBindings = bindings.data();
return new DxvkShader(info, std::move(code));
VkDescriptorSetLayout layout = VK_NULL_HANDLE;
VkResult vr = vk->vkCreateDescriptorSetLayout(vk->device(), &info, nullptr, &layout);
if (vr != VK_SUCCESS)
throw DxvkError(str::format("Failed to create format conversion descriptor set layout: ", vr));
return layout;
}
void D3D9FormatHelper::FlushInternal() {
m_context->flushCommandList(nullptr);
m_transferCommands = 0;
VkPipelineLayout D3D9FormatHelper::CreatePipelineLayout() {
auto vk = m_device->vkd();
VkPushConstantRange pushConstants = { };
pushConstants.size = sizeof(VkExtent2D);
pushConstants.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
VkPipelineLayoutCreateInfo info = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
info.setLayoutCount = 1u;
info.pSetLayouts = &m_setLayout;
info.pushConstantRangeCount = 1u;
info.pPushConstantRanges = &pushConstants;
VkPipelineLayout layout = VK_NULL_HANDLE;
VkResult vr = vk->vkCreatePipelineLayout(vk->device(), &info, nullptr, &layout);
if (vr != VK_SUCCESS)
throw DxvkError(str::format("Failed to create format conversion pipeline layout: ", vr));
return layout;
}
VkPipeline D3D9FormatHelper::CreatePipeline(size_t size, const uint32_t* code, uint32_t specConstant) {
auto vk = m_device->vkd();
VkSpecializationMapEntry specEntry = { };
specEntry.size = sizeof(specConstant);
VkSpecializationInfo specInfo = { };
specInfo.mapEntryCount = 1;
specInfo.pMapEntries = &specEntry;
specInfo.dataSize = sizeof(specConstant);
specInfo.pData = &specConstant;
VkComputePipelineCreateInfo pipelineInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
pipelineInfo.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
pipelineInfo.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
pipelineInfo.stage.pName = "main";
pipelineInfo.stage.pSpecializationInfo = &specInfo;
pipelineInfo.layout = m_pipelineLayout;
pipelineInfo.basePipelineIndex = -1;
VkShaderModuleCreateInfo moduleInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
moduleInfo.codeSize = size;
moduleInfo.pCode = code;
if (m_device->features().khrMaintenance5.maintenance5
|| m_device->features().extGraphicsPipelineLibrary.graphicsPipelineLibrary) {
pipelineInfo.stage.pNext = &moduleInfo;
} else {
VkResult vr = vk->vkCreateShaderModule(vk->device(),
&moduleInfo, nullptr, &pipelineInfo.stage.module);
if (vr != VK_SUCCESS)
throw DxvkError(str::format("Failed to create format conversion shader module: ", vr));
}
VkPipeline pipeline = VK_NULL_HANDLE;
VkResult vr = vk->vkCreateComputePipelines(vk->device(),
VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline);
vk->vkDestroyShaderModule(vk->device(), pipelineInfo.stage.module, nullptr);
if (vr != VK_SUCCESS)
throw DxvkError(str::format("Failed to create format conversion pipeline: ", vr));
return pipeline;
}
}

View File

@ -13,9 +13,12 @@ namespace dxvk {
D3D9FormatHelper(const Rc<DxvkDevice>& device);
~D3D9FormatHelper();
void Flush();
void ConvertFormat(
const DxvkContextObjects& ctx,
D3D9_CONVERSION_FORMAT_INFO conversionFormat,
const Rc<DxvkImage>& dstImage,
VkImageSubresourceLayers dstSubresource,
@ -24,12 +27,12 @@ namespace dxvk {
private:
void ConvertGenericFormat(
const DxvkContextObjects& ctx,
D3D9_CONVERSION_FORMAT_INFO videoFormat,
const Rc<DxvkImage>& dstImage,
VkImageSubresourceLayers dstSubresource,
const DxvkBufferSlice& srcSlice,
VkFormat bufferFormat,
uint32_t specConstantValue,
VkExtent2D macroPixelRun);
enum BindingIds : uint32_t {
@ -37,18 +40,20 @@ namespace dxvk {
Buffer = 1,
};
void InitShaders();
void InitPipelines();
Rc<DxvkShader> InitShader(SpirvCodeBuffer code);
VkDescriptorSetLayout CreateSetLayout();
void FlushInternal();
VkPipelineLayout CreatePipelineLayout();
Rc<DxvkDevice> m_device;
Rc<DxvkContext> m_context;
VkPipeline CreatePipeline(size_t size, const uint32_t* code, uint32_t specConstant);
size_t m_transferCommands = 0;
Rc<DxvkDevice> m_device;
std::array<Rc<DxvkShader>, D3D9ConversionFormat_Count> m_shaders;
VkDescriptorSetLayout m_setLayout = VK_NULL_HANDLE;
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
std::array<VkPipeline, D3D9ConversionFormat_Count> m_pipelines = { };
};