From 9a95c7fa14bdfc14aacea92896c8ae8533918fe8 Mon Sep 17 00:00:00 2001 From: FengChen Date: Thu, 1 Sep 2022 22:05:11 +0800 Subject: video_core: Generate mipmap texture by drawing --- .../renderer_opengl/gl_graphics_pipeline.cpp | 11 ++++++++++ src/video_core/renderer_opengl/gl_rasterizer.cpp | 10 +++++++++ src/video_core/renderer_opengl/gl_shader_cache.cpp | 2 +- src/video_core/renderer_vulkan/pipeline_helper.h | 10 ++++++++- .../renderer_vulkan/vk_graphics_pipeline.cpp | 24 ++++++++++++++++++---- .../renderer_vulkan/vk_graphics_pipeline.h | 4 +++- src/video_core/renderer_vulkan/vk_rasterizer.cpp | 16 +++++++++++++++ src/video_core/shader_environment.cpp | 17 +++++++++++++++ src/video_core/shader_environment.h | 9 ++++++++ 9 files changed, 96 insertions(+), 7 deletions(-) (limited to 'src/video_core') diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index 67eae369d..c297f7121 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp @@ -502,6 +502,17 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { float_image_scaling_mask, down_factor, 0.0f); } } + if (info.uses_render_area) { + const auto render_area_width(static_cast(regs.render_area.width)); + const auto render_area_height(static_cast(regs.render_area.height)); + if (use_assembly) { + glProgramLocalParameter4fARB(AssemblyStage(stage), 1, render_area_width, + render_area_height, 0.0f, 0.0f); + } else { + glProgramUniform4f(source_programs[stage].handle, 1, render_area_width, + render_area_height, 0.0f, 0.0f); + } + } }}; if constexpr (Spec::enabled_stages[0]) { prepare_stage(0); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index a0d048b0b..f018333af 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -622,6 +622,16 @@ void RasterizerOpenGL::SyncViewport() { } flags[Dirty::Viewport0 + index] = false; + if (!regs.viewport_transform_enabled) { + const auto x = static_cast(regs.render_area.x); + const auto y = static_cast(regs.render_area.y); + const auto width = static_cast(regs.render_area.width); + const auto height = static_cast(regs.render_area.height); + glViewportIndexedf(static_cast(index), x, y, width != 0.0f ? width : 1.0f, + height != 0.0f ? height : 1.0f); + continue; + } + const auto& src = regs.viewport_transform[index]; GLfloat x = conv(src.translate_x - src.scale_x); GLfloat y = conv(src.translate_y - src.scale_y); diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 1ad56d9e7..7e76f679f 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -49,7 +49,7 @@ using VideoCommon::LoadPipelines; using VideoCommon::SerializePipeline; using Context = ShaderContext::Context; -constexpr u32 CACHE_VERSION = 5; +constexpr u32 CACHE_VERSION = 7; template auto MakeSpan(Container& container) { diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h index b24f3424a..b7843e995 100644 --- a/src/video_core/renderer_vulkan/pipeline_helper.h +++ b/src/video_core/renderer_vulkan/pipeline_helper.h @@ -68,13 +68,15 @@ public: } vk::PipelineLayout CreatePipelineLayout(VkDescriptorSetLayout descriptor_set_layout) const { + using Shader::Backend::SPIRV::RenderAreaLayout; using Shader::Backend::SPIRV::RescalingLayout; const u32 size_offset = is_compute ? sizeof(RescalingLayout::down_factor) : 0u; const VkPushConstantRange range{ .stageFlags = static_cast( is_compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_ALL_GRAPHICS), .offset = 0, - .size = static_cast(sizeof(RescalingLayout)) - size_offset, + .size = static_cast(sizeof(RescalingLayout)) - size_offset + + static_cast(sizeof(RenderAreaLayout)), }; return device->GetLogical().CreatePipelineLayout({ .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, @@ -167,6 +169,12 @@ private: u32 image_bit{1u}; }; +class RenderAreaPushConstant { +public: + bool uses_render_area{}; + std::array words{}; +}; + inline void PushImageDescriptors(TextureCache& texture_cache, UpdateDescriptorQueue& update_descriptor_queue, const Shader::Info& info, RescalingPushConstant& rescaling, diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 5aca8f038..7eb623a7c 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -31,6 +31,7 @@ namespace { using boost::container::small_vector; using boost::container::static_vector; using Shader::ImageBufferDescriptor; +using Shader::Backend::SPIRV::RENDERAREA_LAYOUT_OFFSET; using Shader::Backend::SPIRV::RESCALING_LAYOUT_DOWN_FACTOR_OFFSET; using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET; using Tegra::Texture::TexturePair; @@ -433,12 +434,19 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { update_descriptor_queue.Acquire(); RescalingPushConstant rescaling; + RenderAreaPushConstant render_area; const VkSampler* samplers_it{samplers.data()}; const VideoCommon::ImageViewInOut* views_it{views.data()}; const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE { buffer_cache.BindHostStageBuffers(stage); PushImageDescriptors(texture_cache, update_descriptor_queue, stage_infos[stage], rescaling, samplers_it, views_it); + const auto& info{stage_infos[0]}; + if (info.uses_render_area) { + render_area.uses_render_area = true; + render_area.words = {static_cast(regs.render_area.width), + static_cast(regs.render_area.height)}; + } }}; if constexpr (Spec::enabled_stages[0]) { prepare_stage(0); @@ -455,10 +463,11 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { if constexpr (Spec::enabled_stages[4]) { prepare_stage(4); } - ConfigureDraw(rescaling); + ConfigureDraw(rescaling, render_area); } -void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling) { +void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling, + const RenderAreaPushConstant& render_are) { texture_cache.UpdateRenderTargets(false); scheduler.RequestRenderpass(texture_cache.GetFramebuffer()); @@ -474,7 +483,9 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling) { const bool bind_pipeline{scheduler.UpdateGraphicsPipeline(this)}; const void* const descriptor_data{update_descriptor_queue.UpdateData()}; scheduler.Record([this, descriptor_data, bind_pipeline, rescaling_data = rescaling.Data(), - is_rescaling, update_rescaling](vk::CommandBuffer cmdbuf) { + is_rescaling, update_rescaling, + uses_render_area = render_are.uses_render_area, + render_area_data = render_are.words](vk::CommandBuffer cmdbuf) { if (bind_pipeline) { cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); } @@ -483,11 +494,16 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling) { rescaling_data.data()); if (update_rescaling) { const f32 config_down_factor{Settings::values.resolution_info.down_factor}; - const f32 scale_down_factor{is_rescaling ? config_down_factor : 1.0f}; + const f32 scale_down_factor{is_rescaling ? config_down_factor : 2.0f}; cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_ALL_GRAPHICS, RESCALING_LAYOUT_DOWN_FACTOR_OFFSET, sizeof(scale_down_factor), &scale_down_factor); } + if (uses_render_area) { + cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_ALL_GRAPHICS, + RENDERAREA_LAYOUT_OFFSET, sizeof(render_area_data), + &render_area_data); + } if (!descriptor_set_layout) { return; } diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index e8949a9ab..8842f62d7 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -62,6 +62,7 @@ class Device; class PipelineStatistics; class RenderPassCache; class RescalingPushConstant; +class RenderAreaPushConstant; class Scheduler; class UpdateDescriptorQueue; @@ -113,7 +114,8 @@ private: template void ConfigureImpl(bool is_indexed); - void ConfigureDraw(const RescalingPushConstant& rescaling); + void ConfigureDraw(const RescalingPushConstant& rescaling, + const RenderAreaPushConstant& render_are); void MakePipeline(VkRenderPass render_pass); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 7e40c2df1..bf9f825f4 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -682,6 +682,22 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg if (!state_tracker.TouchViewports()) { return; } + if (!regs.viewport_transform_enabled) { + const auto x = static_cast(regs.render_area.x); + const auto y = static_cast(regs.render_area.y); + const auto width = static_cast(regs.render_area.width); + const auto height = static_cast(regs.render_area.height); + VkViewport viewport{ + .x = x, + .y = y, + .width = width != 0.0f ? width : 1.0f, + .height = height != 0.0f ? height : 1.0f, + .minDepth = 0.0f, + .maxDepth = 1.0f, + }; + scheduler.Record([viewport](vk::CommandBuffer cmdbuf) { cmdbuf.SetViewport(0, viewport); }); + return; + } const bool is_rescaling{texture_cache.IsRescaling()}; const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f; const std::array viewports{ diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index 808d88eec..3ead06dd6 100644 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp @@ -191,6 +191,8 @@ void GenericEnvironment::Serialize(std::ofstream& file) const { .write(reinterpret_cast(&start_address), sizeof(start_address)) .write(reinterpret_cast(&cached_lowest), sizeof(cached_lowest)) .write(reinterpret_cast(&cached_highest), sizeof(cached_highest)) + .write(reinterpret_cast(&viewport_transform_state), + sizeof(viewport_transform_state)) .write(reinterpret_cast(&stage), sizeof(stage)) .write(reinterpret_cast(code.data()), code_size); for (const auto& [key, type] : texture_types) { @@ -311,6 +313,12 @@ Shader::TextureType GraphicsEnvironment::ReadTextureType(u32 handle) { return ReadTextureTypeImpl(regs.tic.Address(), regs.tic.limit, via_header_index, handle); } +u32 GraphicsEnvironment::ReadViewportTransformState() { + const auto& regs{maxwell3d->regs}; + viewport_transform_state = regs.viewport_transform_enabled; + return viewport_transform_state; +} + ComputeEnvironment::ComputeEnvironment(Tegra::Engines::KeplerCompute& kepler_compute_, Tegra::MemoryManager& gpu_memory_, GPUVAddr program_base_, u32 start_address_) @@ -342,6 +350,10 @@ Shader::TextureType ComputeEnvironment::ReadTextureType(u32 handle) { return ReadTextureTypeImpl(regs.tic.Address(), regs.tic.limit, qmd.linked_tsc != 0, handle); } +u32 ComputeEnvironment::ReadViewportTransformState() { + return viewport_transform_state; +} + void FileEnvironment::Deserialize(std::ifstream& file) { u64 code_size{}; u64 num_texture_types{}; @@ -354,6 +366,7 @@ void FileEnvironment::Deserialize(std::ifstream& file) { .read(reinterpret_cast(&start_address), sizeof(start_address)) .read(reinterpret_cast(&read_lowest), sizeof(read_lowest)) .read(reinterpret_cast(&read_highest), sizeof(read_highest)) + .read(reinterpret_cast(&viewport_transform_state), sizeof(viewport_transform_state)) .read(reinterpret_cast(&stage), sizeof(stage)); code = std::make_unique(Common::DivCeil(code_size, sizeof(u64))); file.read(reinterpret_cast(code.get()), code_size); @@ -411,6 +424,10 @@ Shader::TextureType FileEnvironment::ReadTextureType(u32 handle) { return it->second; } +u32 FileEnvironment::ReadViewportTransformState() { + return viewport_transform_state; +} + u32 FileEnvironment::LocalMemorySize() const { return local_memory_size; } diff --git a/src/video_core/shader_environment.h b/src/video_core/shader_environment.h index 5a145f33a..a0659fd7c 100644 --- a/src/video_core/shader_environment.h +++ b/src/video_core/shader_environment.h @@ -85,6 +85,8 @@ protected: u32 cached_highest = 0; u32 initial_offset = 0; + u32 viewport_transform_state = 1; + bool has_unbound_instructions = false; }; @@ -102,6 +104,8 @@ public: Shader::TextureType ReadTextureType(u32 handle) override; + u32 ReadViewportTransformState() override; + private: Tegra::Engines::Maxwell3D* maxwell3d{}; size_t stage_index{}; @@ -120,6 +124,8 @@ public: Shader::TextureType ReadTextureType(u32 handle) override; + u32 ReadViewportTransformState() override; + private: Tegra::Engines::KeplerCompute* kepler_compute{}; }; @@ -143,6 +149,8 @@ public: [[nodiscard]] Shader::TextureType ReadTextureType(u32 handle) override; + [[nodiscard]] u32 ReadViewportTransformState() override; + [[nodiscard]] u32 LocalMemorySize() const override; [[nodiscard]] u32 SharedMemorySize() const override; @@ -164,6 +172,7 @@ private: u32 read_lowest{}; u32 read_highest{}; u32 initial_offset{}; + u32 viewport_transform_state = 1; }; void SerializePipeline(std::span key, std::span envs, -- cgit v1.2.3