Merge pull request #3518 from ReinUsesLisp/scissor-clears
vk_rasterizer: Implement scissor clears and layered clears
This commit is contained in:
		
						commit
						d787856621
					
				@ -179,10 +179,11 @@ Tegra::Engines::ConstBufferEngineInterface& CachedShader::GetEngine(
 | 
			
		||||
VKPipelineCache::VKPipelineCache(Core::System& system, RasterizerVulkan& rasterizer,
 | 
			
		||||
                                 const VKDevice& device, VKScheduler& scheduler,
 | 
			
		||||
                                 VKDescriptorPool& descriptor_pool,
 | 
			
		||||
                                 VKUpdateDescriptorQueue& update_descriptor_queue)
 | 
			
		||||
                                 VKUpdateDescriptorQueue& update_descriptor_queue,
 | 
			
		||||
                                 VKRenderPassCache& renderpass_cache)
 | 
			
		||||
    : RasterizerCache{rasterizer}, system{system}, device{device}, scheduler{scheduler},
 | 
			
		||||
      descriptor_pool{descriptor_pool}, update_descriptor_queue{update_descriptor_queue},
 | 
			
		||||
      renderpass_cache(device) {}
 | 
			
		||||
      renderpass_cache{renderpass_cache} {}
 | 
			
		||||
 | 
			
		||||
VKPipelineCache::~VKPipelineCache() = default;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -161,7 +161,8 @@ public:
 | 
			
		||||
    explicit VKPipelineCache(Core::System& system, RasterizerVulkan& rasterizer,
 | 
			
		||||
                             const VKDevice& device, VKScheduler& scheduler,
 | 
			
		||||
                             VKDescriptorPool& descriptor_pool,
 | 
			
		||||
                             VKUpdateDescriptorQueue& update_descriptor_queue);
 | 
			
		||||
                             VKUpdateDescriptorQueue& update_descriptor_queue,
 | 
			
		||||
                             VKRenderPassCache& renderpass_cache);
 | 
			
		||||
    ~VKPipelineCache();
 | 
			
		||||
 | 
			
		||||
    std::array<Shader, Maxwell::MaxShaderProgram> GetShaders();
 | 
			
		||||
@ -184,8 +185,7 @@ private:
 | 
			
		||||
    VKScheduler& scheduler;
 | 
			
		||||
    VKDescriptorPool& descriptor_pool;
 | 
			
		||||
    VKUpdateDescriptorQueue& update_descriptor_queue;
 | 
			
		||||
 | 
			
		||||
    VKRenderPassCache renderpass_cache;
 | 
			
		||||
    VKRenderPassCache& renderpass_cache;
 | 
			
		||||
 | 
			
		||||
    std::array<Shader, Maxwell::MaxShaderProgram> last_shaders;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -287,12 +287,13 @@ RasterizerVulkan::RasterizerVulkan(Core::System& system, Core::Frontend::EmuWind
 | 
			
		||||
      screen_info{screen_info}, device{device}, resource_manager{resource_manager},
 | 
			
		||||
      memory_manager{memory_manager}, state_tracker{state_tracker}, scheduler{scheduler},
 | 
			
		||||
      staging_pool(device, memory_manager, scheduler), descriptor_pool(device),
 | 
			
		||||
      update_descriptor_queue(device, scheduler),
 | 
			
		||||
      update_descriptor_queue(device, scheduler), renderpass_cache(device),
 | 
			
		||||
      quad_array_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue),
 | 
			
		||||
      uint8_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue),
 | 
			
		||||
      texture_cache(system, *this, device, resource_manager, memory_manager, scheduler,
 | 
			
		||||
                    staging_pool),
 | 
			
		||||
      pipeline_cache(system, *this, device, scheduler, descriptor_pool, update_descriptor_queue),
 | 
			
		||||
      pipeline_cache(system, *this, device, scheduler, descriptor_pool, update_descriptor_queue,
 | 
			
		||||
                     renderpass_cache),
 | 
			
		||||
      buffer_cache(*this, system, device, memory_manager, scheduler, staging_pool),
 | 
			
		||||
      sampler_cache(device), query_cache(system, *this, device, scheduler) {
 | 
			
		||||
    scheduler.SetQueryCache(query_cache);
 | 
			
		||||
@ -365,13 +366,16 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) {
 | 
			
		||||
void RasterizerVulkan::Clear() {
 | 
			
		||||
    MICROPROFILE_SCOPE(Vulkan_Clearing);
 | 
			
		||||
 | 
			
		||||
    query_cache.UpdateCounters();
 | 
			
		||||
 | 
			
		||||
    const auto& gpu = system.GPU().Maxwell3D();
 | 
			
		||||
    if (!system.GPU().Maxwell3D().ShouldExecute()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sampled_views.clear();
 | 
			
		||||
    image_views.clear();
 | 
			
		||||
 | 
			
		||||
    query_cache.UpdateCounters();
 | 
			
		||||
 | 
			
		||||
    const auto& regs = gpu.regs;
 | 
			
		||||
    const bool use_color = regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
 | 
			
		||||
                           regs.clear_buffers.A;
 | 
			
		||||
@ -380,52 +384,54 @@ void RasterizerVulkan::Clear() {
 | 
			
		||||
    if (!use_color && !use_depth && !use_stencil) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    // Clearing images requires to be out of a renderpass
 | 
			
		||||
    scheduler.RequestOutsideRenderPassOperationContext();
 | 
			
		||||
 | 
			
		||||
    // TODO(Rodrigo): Implement clears rendering a quad or using beginning a renderpass.
 | 
			
		||||
    [[maybe_unused]] const auto texceptions = UpdateAttachments();
 | 
			
		||||
    DEBUG_ASSERT(texceptions.none());
 | 
			
		||||
    SetupImageTransitions(0, color_attachments, zeta_attachment);
 | 
			
		||||
 | 
			
		||||
    const vk::RenderPass renderpass = renderpass_cache.GetRenderPass(GetRenderPassParams(0));
 | 
			
		||||
    const auto [framebuffer, render_area] = ConfigureFramebuffers(renderpass);
 | 
			
		||||
    scheduler.RequestRenderpass({renderpass, framebuffer, {{0, 0}, render_area}, 0, nullptr});
 | 
			
		||||
 | 
			
		||||
    const auto& scissor = regs.scissor_test[0];
 | 
			
		||||
    const vk::Offset2D scissor_offset(scissor.min_x, scissor.min_y);
 | 
			
		||||
    vk::Extent2D scissor_extent{scissor.max_x - scissor.min_x, scissor.max_y - scissor.min_y};
 | 
			
		||||
    scissor_extent.width = std::min(scissor_extent.width, render_area.width);
 | 
			
		||||
    scissor_extent.height = std::min(scissor_extent.height, render_area.height);
 | 
			
		||||
 | 
			
		||||
    const u32 layer = regs.clear_buffers.layer;
 | 
			
		||||
    const vk::ClearRect clear_rect({scissor_offset, scissor_extent}, layer, 1);
 | 
			
		||||
 | 
			
		||||
    if (use_color) {
 | 
			
		||||
        View color_view;
 | 
			
		||||
        {
 | 
			
		||||
            MICROPROFILE_SCOPE(Vulkan_RenderTargets);
 | 
			
		||||
            color_view = texture_cache.GetColorBufferSurface(regs.clear_buffers.RT.Value(), false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        color_view->Transition(vk::ImageLayout::eTransferDstOptimal,
 | 
			
		||||
                               vk::PipelineStageFlagBits::eTransfer,
 | 
			
		||||
                               vk::AccessFlagBits::eTransferWrite);
 | 
			
		||||
 | 
			
		||||
        const std::array clear_color = {regs.clear_color[0], regs.clear_color[1],
 | 
			
		||||
                                        regs.clear_color[2], regs.clear_color[3]};
 | 
			
		||||
        const vk::ClearColorValue clear(clear_color);
 | 
			
		||||
        scheduler.Record([image = color_view->GetImage(),
 | 
			
		||||
                          subresource = color_view->GetImageSubresourceRange(),
 | 
			
		||||
                          clear](auto cmdbuf, auto& dld) {
 | 
			
		||||
            cmdbuf.clearColorImage(image, vk::ImageLayout::eTransferDstOptimal, clear, subresource,
 | 
			
		||||
                                   dld);
 | 
			
		||||
        const vk::ClearValue clear_value{clear_color};
 | 
			
		||||
        const u32 color_attachment = regs.clear_buffers.RT;
 | 
			
		||||
        scheduler.Record([color_attachment, clear_value, clear_rect](auto cmdbuf, auto& dld) {
 | 
			
		||||
            const vk::ClearAttachment attachment(vk::ImageAspectFlagBits::eColor, color_attachment,
 | 
			
		||||
                                                 clear_value);
 | 
			
		||||
            cmdbuf.clearAttachments(1, &attachment, 1, &clear_rect, dld);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    if (use_depth || use_stencil) {
 | 
			
		||||
        View zeta_surface;
 | 
			
		||||
        {
 | 
			
		||||
            MICROPROFILE_SCOPE(Vulkan_RenderTargets);
 | 
			
		||||
            zeta_surface = texture_cache.GetDepthBufferSurface(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        zeta_surface->Transition(vk::ImageLayout::eTransferDstOptimal,
 | 
			
		||||
                                 vk::PipelineStageFlagBits::eTransfer,
 | 
			
		||||
                                 vk::AccessFlagBits::eTransferWrite);
 | 
			
		||||
 | 
			
		||||
        const vk::ClearDepthStencilValue clear(regs.clear_depth,
 | 
			
		||||
                                               static_cast<u32>(regs.clear_stencil));
 | 
			
		||||
        scheduler.Record([image = zeta_surface->GetImage(),
 | 
			
		||||
                          subresource = zeta_surface->GetImageSubresourceRange(),
 | 
			
		||||
                          clear](auto cmdbuf, auto& dld) {
 | 
			
		||||
            cmdbuf.clearDepthStencilImage(image, vk::ImageLayout::eTransferDstOptimal, clear,
 | 
			
		||||
                                          subresource, dld);
 | 
			
		||||
        });
 | 
			
		||||
    if (!use_depth && !use_stencil) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    vk::ImageAspectFlags aspect_flags;
 | 
			
		||||
    if (use_depth) {
 | 
			
		||||
        aspect_flags |= vk::ImageAspectFlagBits::eDepth;
 | 
			
		||||
    }
 | 
			
		||||
    if (use_stencil) {
 | 
			
		||||
        aspect_flags |= vk::ImageAspectFlagBits::eStencil;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    scheduler.Record([clear_depth = regs.clear_depth, clear_stencil = regs.clear_stencil,
 | 
			
		||||
                      clear_rect, aspect_flags](auto cmdbuf, auto& dld) {
 | 
			
		||||
        const vk::ClearDepthStencilValue clear_zeta(clear_depth, clear_stencil);
 | 
			
		||||
        const vk::ClearValue clear_value{clear_zeta};
 | 
			
		||||
        const vk::ClearAttachment attachment(aspect_flags, 0, clear_value);
 | 
			
		||||
        cmdbuf.clearAttachments(1, &attachment, 1, &clear_rect, dld);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerVulkan::DispatchCompute(GPUVAddr code_addr) {
 | 
			
		||||
 | 
			
		||||
@ -253,6 +253,7 @@ private:
 | 
			
		||||
    VKStagingBufferPool staging_pool;
 | 
			
		||||
    VKDescriptorPool descriptor_pool;
 | 
			
		||||
    VKUpdateDescriptorQueue update_descriptor_queue;
 | 
			
		||||
    VKRenderPassCache renderpass_cache;
 | 
			
		||||
    QuadArrayPass quad_array_pass;
 | 
			
		||||
    Uint8Pass uint8_pass;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user