diff --git a/src/dxvk/dxvk_meta_clear.cpp b/src/dxvk/dxvk_meta_clear.cpp index 071cde286..25269bda4 100644 --- a/src/dxvk/dxvk_meta_clear.cpp +++ b/src/dxvk/dxvk_meta_clear.cpp @@ -1,15 +1,166 @@ #include "dxvk_meta_clear.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + namespace dxvk { DxvkMetaClearObjects::DxvkMetaClearObjects(const Rc& vkd) : m_vkd(vkd) { + // Create descriptor set layouts + m_clearBufDsetLayout = createDescriptorSetLayout(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); + m_clearImgDsetLayout = createDescriptorSetLayout(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); + // Create pipeline layouts using those descriptor set layouts + m_clearBufPipeLayout = createPipelineLayout(m_clearBufDsetLayout); + m_clearImgPipeLayout = createPipelineLayout(m_clearImgDsetLayout); + + // Create the actual compute pipelines + m_clearPipesF32.clearBuf = createPipeline(dxvk_clear_buffer_f, m_clearBufPipeLayout); + m_clearPipesU32.clearBuf = createPipeline(dxvk_clear_buffer_u, m_clearBufPipeLayout); + + m_clearPipesF32.clearImg1D = createPipeline(dxvk_clear_image1d_f, m_clearImgPipeLayout); + m_clearPipesU32.clearImg1D = createPipeline(dxvk_clear_image1d_u, m_clearImgPipeLayout); + m_clearPipesF32.clearImg2D = createPipeline(dxvk_clear_image2d_f, m_clearImgPipeLayout); + m_clearPipesU32.clearImg2D = createPipeline(dxvk_clear_image2d_u, m_clearImgPipeLayout); + m_clearPipesF32.clearImg3D = createPipeline(dxvk_clear_image3d_f, m_clearImgPipeLayout); + m_clearPipesU32.clearImg3D = createPipeline(dxvk_clear_image3d_u, m_clearImgPipeLayout); + + m_clearPipesF32.clearImg1DArray = createPipeline(dxvk_clear_image1darr_f, m_clearImgPipeLayout); + m_clearPipesU32.clearImg1DArray = createPipeline(dxvk_clear_image1darr_u, m_clearImgPipeLayout); + m_clearPipesF32.clearImg2DArray = createPipeline(dxvk_clear_image2darr_f, m_clearImgPipeLayout); + m_clearPipesU32.clearImg2DArray = createPipeline(dxvk_clear_image2darr_u, m_clearImgPipeLayout); } DxvkMetaClearObjects::~DxvkMetaClearObjects() { + // Destroy pipelines + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesF32.clearBuf, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesU32.clearBuf, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesF32.clearImg1D, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesU32.clearImg1D, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesF32.clearImg2D, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesU32.clearImg2D, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesF32.clearImg3D, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesU32.clearImg3D, nullptr); + + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesF32.clearImg1DArray, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesU32.clearImg1DArray, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesF32.clearImg2DArray, nullptr); + m_vkd->vkDestroyPipeline(m_vkd->device(), m_clearPipesU32.clearImg2DArray, nullptr); + + // Destroy pipeline layouts + m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_clearBufPipeLayout, nullptr); + m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_clearImgPipeLayout, nullptr); + + // Destroy descriptor set layouts + m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_clearBufDsetLayout, nullptr); + m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_clearImgDsetLayout, nullptr); + } + + + VkDescriptorSetLayout DxvkMetaClearObjects::createDescriptorSetLayout( + VkDescriptorType descriptorType) { + VkDescriptorSetLayoutBinding bindInfo; + bindInfo.binding = 0; + bindInfo.descriptorType = descriptorType; + bindInfo.descriptorCount = 1; + bindInfo.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + bindInfo.pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutCreateInfo dsetInfo; + dsetInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + dsetInfo.pNext = nullptr; + dsetInfo.flags = 0; + dsetInfo.bindingCount = 1; + dsetInfo.pBindings = &bindInfo; + + VkDescriptorSetLayout result = VK_NULL_HANDLE; + if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(), + &dsetInfo, nullptr, &result) != VK_SUCCESS) + throw DxvkError("Dxvk: Failed to create meta clear descriptor set layout"); + return result; + } + + + VkPipelineLayout DxvkMetaClearObjects::createPipelineLayout( + VkDescriptorSetLayout dsetLayout) { + VkPushConstantRange pushInfo; + pushInfo.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + pushInfo.offset = 0; + pushInfo.size = sizeof(DxvkMetaClearArgs); + + VkPipelineLayoutCreateInfo pipeInfo; + pipeInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipeInfo.pNext = nullptr; + pipeInfo.flags = 0; + pipeInfo.setLayoutCount = 1; + pipeInfo.pSetLayouts = &dsetLayout; + pipeInfo.pushConstantRangeCount = 1; + pipeInfo.pPushConstantRanges = &pushInfo; + + VkPipelineLayout result = VK_NULL_HANDLE; + if (m_vkd->vkCreatePipelineLayout(m_vkd->device(), + &pipeInfo, nullptr, &result) != VK_SUCCESS) + throw DxvkError("Dxvk: Failed to create meta clear pipeline layout"); + return result; + } + + + VkPipeline DxvkMetaClearObjects::createPipeline( + const SpirvCodeBuffer& spirvCode, + VkPipelineLayout pipeLayout) { + VkShaderModuleCreateInfo shaderInfo; + shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shaderInfo.pNext = nullptr; + shaderInfo.flags = 0; + shaderInfo.codeSize = spirvCode.size(); + shaderInfo.pCode = spirvCode.data(); + + VkShaderModule shaderModule = VK_NULL_HANDLE; + if (m_vkd->vkCreateShaderModule(m_vkd->device(), + &shaderInfo, nullptr, &shaderModule) != VK_SUCCESS) + throw DxvkError("Dxvk: Failed to create meta clear shader module"); + + VkPipelineShaderStageCreateInfo stageInfo; + stageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stageInfo.pNext = nullptr; + stageInfo.flags = 0; + stageInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT; + stageInfo.module = shaderModule; + stageInfo.pName = "main"; + stageInfo.pSpecializationInfo = nullptr; + + VkComputePipelineCreateInfo pipeInfo; + pipeInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + pipeInfo.pNext = nullptr; + pipeInfo.flags = 0; + pipeInfo.stage = stageInfo; + pipeInfo.layout = pipeLayout; + pipeInfo.basePipelineHandle = VK_NULL_HANDLE; + pipeInfo.basePipelineIndex = -1; + + VkPipeline result = VK_NULL_HANDLE; + + const VkResult status = m_vkd->vkCreateComputePipelines( + m_vkd->device(), VK_NULL_HANDLE, 1, &pipeInfo, nullptr, &result); + + m_vkd->vkDestroyShaderModule(m_vkd->device(), shaderModule, nullptr); + + if (status != VK_SUCCESS) + throw DxvkError("Dxvk: Failed to create meta clear compute pipeline"); + return result; } } diff --git a/src/dxvk/dxvk_meta_clear.h b/src/dxvk/dxvk_meta_clear.h index 769025726..ba090096f 100644 --- a/src/dxvk/dxvk_meta_clear.h +++ b/src/dxvk/dxvk_meta_clear.h @@ -4,6 +4,8 @@ #include "dxvk_cmdlist.h" #include "dxvk_resource.h" +#include "../spirv/spirv_code_buffer.h" + namespace dxvk { /** @@ -36,8 +38,36 @@ namespace dxvk { private: + struct DxvkMetaClearPipelines { + VkPipeline clearBuf = VK_NULL_HANDLE; + VkPipeline clearImg1D = VK_NULL_HANDLE; + VkPipeline clearImg2D = VK_NULL_HANDLE; + VkPipeline clearImg3D = VK_NULL_HANDLE; + VkPipeline clearImg1DArray = VK_NULL_HANDLE; + VkPipeline clearImg2DArray = VK_NULL_HANDLE; + }; + Rc m_vkd; + VkDescriptorSetLayout m_clearBufDsetLayout = VK_NULL_HANDLE; + VkDescriptorSetLayout m_clearImgDsetLayout = VK_NULL_HANDLE; + + VkPipelineLayout m_clearBufPipeLayout = VK_NULL_HANDLE; + VkPipelineLayout m_clearImgPipeLayout = VK_NULL_HANDLE; + + DxvkMetaClearPipelines m_clearPipesF32; + DxvkMetaClearPipelines m_clearPipesU32; + + VkDescriptorSetLayout createDescriptorSetLayout( + VkDescriptorType descriptorType); + + VkPipelineLayout createPipelineLayout( + VkDescriptorSetLayout dsetLayout); + + VkPipeline createPipeline( + const SpirvCodeBuffer& spirvCode, + VkPipelineLayout pipeLayout); + }; }