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:
parent
f9a99e81f4
commit
b4ed108105
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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 = { };
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user