diff options
Diffstat (limited to 'src')
19 files changed, 291 insertions, 138 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index aa271a377..f9001104c 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -99,6 +99,8 @@ add_library(video_core STATIC | |||
| 99 | renderer_null/null_rasterizer.h | 99 | renderer_null/null_rasterizer.h |
| 100 | renderer_null/renderer_null.cpp | 100 | renderer_null/renderer_null.cpp |
| 101 | renderer_null/renderer_null.h | 101 | renderer_null/renderer_null.h |
| 102 | renderer_opengl/blit_image.cpp | ||
| 103 | renderer_opengl/blit_image.h | ||
| 102 | renderer_opengl/gl_buffer_cache.cpp | 104 | renderer_opengl/gl_buffer_cache.cpp |
| 103 | renderer_opengl/gl_buffer_cache.h | 105 | renderer_opengl/gl_buffer_cache.h |
| 104 | renderer_opengl/gl_compute_pipeline.cpp | 106 | renderer_opengl/gl_compute_pipeline.cpp |
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index e6dc24f22..1a7961cb9 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt | |||
| @@ -11,6 +11,7 @@ set(GLSL_INCLUDES | |||
| 11 | 11 | ||
| 12 | set(SHADER_FILES | 12 | set(SHADER_FILES |
| 13 | astc_decoder.comp | 13 | astc_decoder.comp |
| 14 | blit_color_float.frag | ||
| 14 | block_linear_unswizzle_2d.comp | 15 | block_linear_unswizzle_2d.comp |
| 15 | block_linear_unswizzle_3d.comp | 16 | block_linear_unswizzle_3d.comp |
| 16 | convert_abgr8_to_d24s8.frag | 17 | convert_abgr8_to_d24s8.frag |
| @@ -36,7 +37,6 @@ set(SHADER_FILES | |||
| 36 | smaa_blending_weight_calculation.frag | 37 | smaa_blending_weight_calculation.frag |
| 37 | smaa_neighborhood_blending.vert | 38 | smaa_neighborhood_blending.vert |
| 38 | smaa_neighborhood_blending.frag | 39 | smaa_neighborhood_blending.frag |
| 39 | vulkan_blit_color_float.frag | ||
| 40 | vulkan_blit_depth_stencil.frag | 40 | vulkan_blit_depth_stencil.frag |
| 41 | vulkan_fidelityfx_fsr_easu_fp16.comp | 41 | vulkan_fidelityfx_fsr_easu_fp16.comp |
| 42 | vulkan_fidelityfx_fsr_easu_fp32.comp | 42 | vulkan_fidelityfx_fsr_easu_fp32.comp |
diff --git a/src/video_core/host_shaders/full_screen_triangle.vert b/src/video_core/host_shaders/full_screen_triangle.vert index 2c976b19f..8ac936efd 100644 --- a/src/video_core/host_shaders/full_screen_triangle.vert +++ b/src/video_core/host_shaders/full_screen_triangle.vert | |||
| @@ -4,13 +4,20 @@ | |||
| 4 | #version 450 | 4 | #version 450 |
| 5 | 5 | ||
| 6 | #ifdef VULKAN | 6 | #ifdef VULKAN |
| 7 | #define VERTEX_ID gl_VertexIndex | ||
| 7 | #define BEGIN_PUSH_CONSTANTS layout(push_constant) uniform PushConstants { | 8 | #define BEGIN_PUSH_CONSTANTS layout(push_constant) uniform PushConstants { |
| 8 | #define END_PUSH_CONSTANTS }; | 9 | #define END_PUSH_CONSTANTS }; |
| 9 | #define UNIFORM(n) | 10 | #define UNIFORM(n) |
| 11 | #define FLIPY 1 | ||
| 10 | #else // ^^^ Vulkan ^^^ // vvv OpenGL vvv | 12 | #else // ^^^ Vulkan ^^^ // vvv OpenGL vvv |
| 13 | #define VERTEX_ID gl_VertexID | ||
| 11 | #define BEGIN_PUSH_CONSTANTS | 14 | #define BEGIN_PUSH_CONSTANTS |
| 12 | #define END_PUSH_CONSTANTS | 15 | #define END_PUSH_CONSTANTS |
| 16 | #define FLIPY -1 | ||
| 13 | #define UNIFORM(n) layout (location = n) uniform | 17 | #define UNIFORM(n) layout (location = n) uniform |
| 18 | out gl_PerVertex { | ||
| 19 | vec4 gl_Position; | ||
| 20 | }; | ||
| 14 | #endif | 21 | #endif |
| 15 | 22 | ||
| 16 | BEGIN_PUSH_CONSTANTS | 23 | BEGIN_PUSH_CONSTANTS |
| @@ -21,8 +28,8 @@ END_PUSH_CONSTANTS | |||
| 21 | layout(location = 0) out vec2 texcoord; | 28 | layout(location = 0) out vec2 texcoord; |
| 22 | 29 | ||
| 23 | void main() { | 30 | void main() { |
| 24 | float x = float((gl_VertexIndex & 1) << 2); | 31 | float x = float((VERTEX_ID & 1) << 2); |
| 25 | float y = float((gl_VertexIndex & 2) << 1); | 32 | float y = float((VERTEX_ID & 2) << 1); |
| 26 | gl_Position = vec4(x - 1.0, y - 1.0, 0.0, 1.0); | 33 | gl_Position = vec4(x - 1.0, FLIPY * (y - 1.0), 0.0, 1.0); |
| 27 | texcoord = fma(vec2(x, y) / 2.0, tex_scale, tex_offset); | 34 | texcoord = fma(vec2(x, y) / 2.0, tex_scale, tex_offset); |
| 28 | } | 35 | } \ No newline at end of file |
diff --git a/src/video_core/host_shaders/vulkan_blit_color_float.frag b/src/video_core/host_shaders/vulkan_blit_color_float.frag deleted file mode 100644 index c0c832296..000000000 --- a/src/video_core/host_shaders/vulkan_blit_color_float.frag +++ /dev/null | |||
| @@ -1,13 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #version 450 | ||
| 5 | |||
| 6 | layout(binding = 0) uniform sampler2D tex; | ||
| 7 | |||
| 8 | layout(location = 0) in vec2 texcoord; | ||
| 9 | layout(location = 0) out vec4 color; | ||
| 10 | |||
| 11 | void main() { | ||
| 12 | color = textureLod(tex, texcoord, 0); | ||
| 13 | } | ||
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index f44c7df50..f980b12c6 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h | |||
| @@ -46,6 +46,9 @@ public: | |||
| 46 | /// Dispatches an indirect draw invocation | 46 | /// Dispatches an indirect draw invocation |
| 47 | virtual void DrawIndirect() {} | 47 | virtual void DrawIndirect() {} |
| 48 | 48 | ||
| 49 | /// Dispatches an draw texture invocation | ||
| 50 | virtual void DrawTexture() = 0; | ||
| 51 | |||
| 49 | /// Clear the current framebuffer | 52 | /// Clear the current framebuffer |
| 50 | virtual void Clear(u32 layer_count) = 0; | 53 | virtual void Clear(u32 layer_count) = 0; |
| 51 | 54 | ||
diff --git a/src/video_core/renderer_null/null_rasterizer.cpp b/src/video_core/renderer_null/null_rasterizer.cpp index 2c11345d7..2b5c7defa 100644 --- a/src/video_core/renderer_null/null_rasterizer.cpp +++ b/src/video_core/renderer_null/null_rasterizer.cpp | |||
| @@ -21,6 +21,7 @@ RasterizerNull::RasterizerNull(Core::Memory::Memory& cpu_memory_, Tegra::GPU& gp | |||
| 21 | RasterizerNull::~RasterizerNull() = default; | 21 | RasterizerNull::~RasterizerNull() = default; |
| 22 | 22 | ||
| 23 | void RasterizerNull::Draw(bool is_indexed, u32 instance_count) {} | 23 | void RasterizerNull::Draw(bool is_indexed, u32 instance_count) {} |
| 24 | void RasterizerNull::DrawTexture() {} | ||
| 24 | void RasterizerNull::Clear(u32 layer_count) {} | 25 | void RasterizerNull::Clear(u32 layer_count) {} |
| 25 | void RasterizerNull::DispatchCompute() {} | 26 | void RasterizerNull::DispatchCompute() {} |
| 26 | void RasterizerNull::ResetCounter(VideoCore::QueryType type) {} | 27 | void RasterizerNull::ResetCounter(VideoCore::QueryType type) {} |
diff --git a/src/video_core/renderer_null/null_rasterizer.h b/src/video_core/renderer_null/null_rasterizer.h index 2112aa70e..51f896e43 100644 --- a/src/video_core/renderer_null/null_rasterizer.h +++ b/src/video_core/renderer_null/null_rasterizer.h | |||
| @@ -31,6 +31,7 @@ public: | |||
| 31 | ~RasterizerNull() override; | 31 | ~RasterizerNull() override; |
| 32 | 32 | ||
| 33 | void Draw(bool is_indexed, u32 instance_count) override; | 33 | void Draw(bool is_indexed, u32 instance_count) override; |
| 34 | void DrawTexture() override; | ||
| 34 | void Clear(u32 layer_count) override; | 35 | void Clear(u32 layer_count) override; |
| 35 | void DispatchCompute() override; | 36 | void DispatchCompute() override; |
| 36 | void ResetCounter(VideoCore::QueryType type) override; | 37 | void ResetCounter(VideoCore::QueryType type) override; |
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index cee5c3247..22ed16ebf 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -166,6 +166,7 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) { | |||
| 166 | has_shader_int64 = HasExtension(extensions, "GL_ARB_gpu_shader_int64"); | 166 | has_shader_int64 = HasExtension(extensions, "GL_ARB_gpu_shader_int64"); |
| 167 | has_amd_shader_half_float = GLAD_GL_AMD_gpu_shader_half_float; | 167 | has_amd_shader_half_float = GLAD_GL_AMD_gpu_shader_half_float; |
| 168 | has_sparse_texture_2 = GLAD_GL_ARB_sparse_texture2; | 168 | has_sparse_texture_2 = GLAD_GL_ARB_sparse_texture2; |
| 169 | has_draw_texture = GLAD_GL_NV_draw_texture; | ||
| 169 | warp_size_potentially_larger_than_guest = !is_nvidia && !is_intel; | 170 | warp_size_potentially_larger_than_guest = !is_nvidia && !is_intel; |
| 170 | need_fastmath_off = is_nvidia; | 171 | need_fastmath_off = is_nvidia; |
| 171 | can_report_memory = GLAD_GL_NVX_gpu_memory_info; | 172 | can_report_memory = GLAD_GL_NVX_gpu_memory_info; |
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index 2a72d84be..3ff8cad83 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <cstddef> | 6 | #include <cstddef> |
| 7 | #include <string> | ||
| 8 | |||
| 7 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 8 | #include "core/frontend/emu_window.h" | 10 | #include "core/frontend/emu_window.h" |
| 9 | #include "shader_recompiler/stage.h" | 11 | #include "shader_recompiler/stage.h" |
| @@ -146,6 +148,10 @@ public: | |||
| 146 | return has_sparse_texture_2; | 148 | return has_sparse_texture_2; |
| 147 | } | 149 | } |
| 148 | 150 | ||
| 151 | bool HasDrawTexture() const { | ||
| 152 | return has_draw_texture; | ||
| 153 | } | ||
| 154 | |||
| 149 | bool IsWarpSizePotentiallyLargerThanGuest() const { | 155 | bool IsWarpSizePotentiallyLargerThanGuest() const { |
| 150 | return warp_size_potentially_larger_than_guest; | 156 | return warp_size_potentially_larger_than_guest; |
| 151 | } | 157 | } |
| @@ -216,6 +222,7 @@ private: | |||
| 216 | bool has_shader_int64{}; | 222 | bool has_shader_int64{}; |
| 217 | bool has_amd_shader_half_float{}; | 223 | bool has_amd_shader_half_float{}; |
| 218 | bool has_sparse_texture_2{}; | 224 | bool has_sparse_texture_2{}; |
| 225 | bool has_draw_texture{}; | ||
| 219 | bool warp_size_potentially_larger_than_guest{}; | 226 | bool warp_size_potentially_larger_than_guest{}; |
| 220 | bool need_fastmath_off{}; | 227 | bool need_fastmath_off{}; |
| 221 | bool has_cbuf_ftou_bug{}; | 228 | bool has_cbuf_ftou_bug{}; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 7d48af8e1..651608a06 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -64,7 +64,8 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra | |||
| 64 | shader_cache(*this, emu_window_, device, texture_cache, buffer_cache, program_manager, | 64 | shader_cache(*this, emu_window_, device, texture_cache, buffer_cache, program_manager, |
| 65 | state_tracker, gpu.ShaderNotify()), | 65 | state_tracker, gpu.ShaderNotify()), |
| 66 | query_cache(*this), accelerate_dma(buffer_cache), | 66 | query_cache(*this), accelerate_dma(buffer_cache), |
| 67 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache) {} | 67 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache), |
| 68 | blit_image(program_manager_) {} | ||
| 68 | 69 | ||
| 69 | RasterizerOpenGL::~RasterizerOpenGL() = default; | 70 | RasterizerOpenGL::~RasterizerOpenGL() = default; |
| 70 | 71 | ||
| @@ -318,6 +319,47 @@ void RasterizerOpenGL::DrawIndirect() { | |||
| 318 | buffer_cache.SetDrawIndirect(nullptr); | 319 | buffer_cache.SetDrawIndirect(nullptr); |
| 319 | } | 320 | } |
| 320 | 321 | ||
| 322 | void RasterizerOpenGL::DrawTexture() { | ||
| 323 | MICROPROFILE_SCOPE(OpenGL_Drawing); | ||
| 324 | |||
| 325 | SCOPE_EXIT({ gpu.TickWork(); }); | ||
| 326 | query_cache.UpdateCounters(); | ||
| 327 | |||
| 328 | texture_cache.SynchronizeGraphicsDescriptors(); | ||
| 329 | texture_cache.UpdateRenderTargets(false); | ||
| 330 | |||
| 331 | SyncState(); | ||
| 332 | |||
| 333 | const auto& draw_texture_state = maxwell3d->draw_manager->GetDrawTextureState(); | ||
| 334 | const auto& sampler = texture_cache.GetGraphicsSampler(draw_texture_state.src_sampler); | ||
| 335 | const auto& texture = texture_cache.GetImageView(draw_texture_state.src_texture); | ||
| 336 | |||
| 337 | if (device.HasDrawTexture()) { | ||
| 338 | state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle()); | ||
| 339 | |||
| 340 | glDrawTextureNV(texture.DefaultHandle(), sampler->Handle(), draw_texture_state.dst_x0, | ||
| 341 | draw_texture_state.dst_y0, draw_texture_state.dst_x1, | ||
| 342 | draw_texture_state.dst_y1, 0, | ||
| 343 | draw_texture_state.src_x0 / static_cast<float>(texture.size.width), | ||
| 344 | draw_texture_state.src_y0 / static_cast<float>(texture.size.height), | ||
| 345 | draw_texture_state.src_x1 / static_cast<float>(texture.size.width), | ||
| 346 | draw_texture_state.src_y1 / static_cast<float>(texture.size.height)); | ||
| 347 | } else { | ||
| 348 | Region2D dst_region = {Offset2D{.x = static_cast<s32>(draw_texture_state.dst_x0), | ||
| 349 | .y = static_cast<s32>(draw_texture_state.dst_y0)}, | ||
| 350 | Offset2D{.x = static_cast<s32>(draw_texture_state.dst_x1), | ||
| 351 | .y = static_cast<s32>(draw_texture_state.dst_y1)}}; | ||
| 352 | Region2D src_region = {Offset2D{.x = static_cast<s32>(draw_texture_state.src_x0), | ||
| 353 | .y = static_cast<s32>(draw_texture_state.src_y0)}, | ||
| 354 | Offset2D{.x = static_cast<s32>(draw_texture_state.src_x1), | ||
| 355 | .y = static_cast<s32>(draw_texture_state.src_y1)}}; | ||
| 356 | blit_image.BlitColor(texture_cache.GetFramebuffer()->Handle(), texture.DefaultHandle(), | ||
| 357 | sampler->Handle(), dst_region, src_region, texture.size); | ||
| 358 | } | ||
| 359 | |||
| 360 | ++num_queued_commands; | ||
| 361 | } | ||
| 362 | |||
| 321 | void RasterizerOpenGL::DispatchCompute() { | 363 | void RasterizerOpenGL::DispatchCompute() { |
| 322 | ComputePipeline* const pipeline{shader_cache.CurrentComputePipeline()}; | 364 | ComputePipeline* const pipeline{shader_cache.CurrentComputePipeline()}; |
| 323 | if (!pipeline) { | 365 | if (!pipeline) { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index be4f76c18..0c45832ae 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include "video_core/engines/maxwell_dma.h" | 16 | #include "video_core/engines/maxwell_dma.h" |
| 17 | #include "video_core/rasterizer_accelerated.h" | 17 | #include "video_core/rasterizer_accelerated.h" |
| 18 | #include "video_core/rasterizer_interface.h" | 18 | #include "video_core/rasterizer_interface.h" |
| 19 | #include "video_core/renderer_opengl/blit_image.h" | ||
| 19 | #include "video_core/renderer_opengl/gl_buffer_cache.h" | 20 | #include "video_core/renderer_opengl/gl_buffer_cache.h" |
| 20 | #include "video_core/renderer_opengl/gl_device.h" | 21 | #include "video_core/renderer_opengl/gl_device.h" |
| 21 | #include "video_core/renderer_opengl/gl_fence_manager.h" | 22 | #include "video_core/renderer_opengl/gl_fence_manager.h" |
| @@ -70,6 +71,7 @@ public: | |||
| 70 | 71 | ||
| 71 | void Draw(bool is_indexed, u32 instance_count) override; | 72 | void Draw(bool is_indexed, u32 instance_count) override; |
| 72 | void DrawIndirect() override; | 73 | void DrawIndirect() override; |
| 74 | void DrawTexture() override; | ||
| 73 | void Clear(u32 layer_count) override; | 75 | void Clear(u32 layer_count) override; |
| 74 | void DispatchCompute() override; | 76 | void DispatchCompute() override; |
| 75 | void ResetCounter(VideoCore::QueryType type) override; | 77 | void ResetCounter(VideoCore::QueryType type) override; |
| @@ -224,6 +226,8 @@ private: | |||
| 224 | AccelerateDMA accelerate_dma; | 226 | AccelerateDMA accelerate_dma; |
| 225 | FenceManagerOpenGL fence_manager; | 227 | FenceManagerOpenGL fence_manager; |
| 226 | 228 | ||
| 229 | BlitImageHelper blit_image; | ||
| 230 | |||
| 227 | boost::container::static_vector<u32, MAX_IMAGE_VIEWS> image_view_indices; | 231 | boost::container::static_vector<u32, MAX_IMAGE_VIEWS> image_view_indices; |
| 228 | std::array<ImageViewId, MAX_IMAGE_VIEWS> image_view_ids; | 232 | std::array<ImageViewId, MAX_IMAGE_VIEWS> image_view_ids; |
| 229 | boost::container::static_vector<GLuint, MAX_TEXTURES> sampler_handles; | 233 | boost::container::static_vector<GLuint, MAX_TEXTURES> sampler_handles; |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index d9c29d8b7..98841ae65 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp | |||
| @@ -1,2 +1,123 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | |||
| 4 | #include <glad/glad.h> | ||
| 5 | |||
| 6 | #include "video_core/renderer_opengl/gl_shader_manager.h" | ||
| 7 | |||
| 8 | namespace OpenGL { | ||
| 9 | |||
| 10 | static constexpr std::array ASSEMBLY_PROGRAM_ENUMS{ | ||
| 11 | GL_VERTEX_PROGRAM_NV, GL_TESS_CONTROL_PROGRAM_NV, GL_TESS_EVALUATION_PROGRAM_NV, | ||
| 12 | GL_GEOMETRY_PROGRAM_NV, GL_FRAGMENT_PROGRAM_NV, | ||
| 13 | }; | ||
| 14 | |||
| 15 | ProgramManager::ProgramManager(const Device& device) { | ||
| 16 | glCreateProgramPipelines(1, &pipeline.handle); | ||
| 17 | if (device.UseAssemblyShaders()) { | ||
| 18 | glEnable(GL_COMPUTE_PROGRAM_NV); | ||
| 19 | } | ||
| 20 | } | ||
| 21 | |||
| 22 | void ProgramManager::BindComputeProgram(GLuint program) { | ||
| 23 | glUseProgram(program); | ||
| 24 | is_compute_bound = true; | ||
| 25 | } | ||
| 26 | |||
| 27 | void ProgramManager::BindComputeAssemblyProgram(GLuint program) { | ||
| 28 | if (current_assembly_compute_program != program) { | ||
| 29 | current_assembly_compute_program = program; | ||
| 30 | glBindProgramARB(GL_COMPUTE_PROGRAM_NV, program); | ||
| 31 | } | ||
| 32 | UnbindPipeline(); | ||
| 33 | } | ||
| 34 | |||
| 35 | void ProgramManager::BindSourcePrograms(std::span<const OGLProgram, NUM_STAGES> programs) { | ||
| 36 | static constexpr std::array<GLenum, 5> stage_enums{ | ||
| 37 | GL_VERTEX_SHADER_BIT, GL_TESS_CONTROL_SHADER_BIT, GL_TESS_EVALUATION_SHADER_BIT, | ||
| 38 | GL_GEOMETRY_SHADER_BIT, GL_FRAGMENT_SHADER_BIT, | ||
| 39 | }; | ||
| 40 | for (size_t stage = 0; stage < NUM_STAGES; ++stage) { | ||
| 41 | if (current_programs[stage] != programs[stage].handle) { | ||
| 42 | current_programs[stage] = programs[stage].handle; | ||
| 43 | glUseProgramStages(pipeline.handle, stage_enums[stage], programs[stage].handle); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | BindPipeline(); | ||
| 47 | } | ||
| 48 | |||
| 49 | void ProgramManager::BindPresentPrograms(GLuint vertex, GLuint fragment) { | ||
| 50 | if (current_programs[0] != vertex) { | ||
| 51 | current_programs[0] = vertex; | ||
| 52 | glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, vertex); | ||
| 53 | } | ||
| 54 | if (current_programs[4] != fragment) { | ||
| 55 | current_programs[4] = fragment; | ||
| 56 | glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, fragment); | ||
| 57 | } | ||
| 58 | glUseProgramStages( | ||
| 59 | pipeline.handle, | ||
| 60 | GL_TESS_CONTROL_SHADER_BIT | GL_TESS_EVALUATION_SHADER_BIT | GL_GEOMETRY_SHADER_BIT, 0); | ||
| 61 | current_programs[1] = 0; | ||
| 62 | current_programs[2] = 0; | ||
| 63 | current_programs[3] = 0; | ||
| 64 | |||
| 65 | if (current_stage_mask != 0) { | ||
| 66 | current_stage_mask = 0; | ||
| 67 | for (const GLenum program_type : ASSEMBLY_PROGRAM_ENUMS) { | ||
| 68 | glDisable(program_type); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | BindPipeline(); | ||
| 72 | } | ||
| 73 | |||
| 74 | void ProgramManager::BindAssemblyPrograms(std::span<const OGLAssemblyProgram, NUM_STAGES> programs, | ||
| 75 | u32 stage_mask) { | ||
| 76 | const u32 changed_mask = current_stage_mask ^ stage_mask; | ||
| 77 | current_stage_mask = stage_mask; | ||
| 78 | |||
| 79 | if (changed_mask != 0) { | ||
| 80 | for (size_t stage = 0; stage < NUM_STAGES; ++stage) { | ||
| 81 | if (((changed_mask >> stage) & 1) != 0) { | ||
| 82 | if (((stage_mask >> stage) & 1) != 0) { | ||
| 83 | glEnable(ASSEMBLY_PROGRAM_ENUMS[stage]); | ||
| 84 | } else { | ||
| 85 | glDisable(ASSEMBLY_PROGRAM_ENUMS[stage]); | ||
| 86 | } | ||
| 87 | } | ||
| 88 | } | ||
| 89 | } | ||
| 90 | for (size_t stage = 0; stage < NUM_STAGES; ++stage) { | ||
| 91 | if (current_programs[stage] != programs[stage].handle) { | ||
| 92 | current_programs[stage] = programs[stage].handle; | ||
| 93 | glBindProgramARB(ASSEMBLY_PROGRAM_ENUMS[stage], programs[stage].handle); | ||
| 94 | } | ||
| 95 | } | ||
| 96 | UnbindPipeline(); | ||
| 97 | } | ||
| 98 | |||
| 99 | void ProgramManager::RestoreGuestCompute() {} | ||
| 100 | |||
| 101 | void ProgramManager::BindPipeline() { | ||
| 102 | if (!is_pipeline_bound) { | ||
| 103 | is_pipeline_bound = true; | ||
| 104 | glBindProgramPipeline(pipeline.handle); | ||
| 105 | } | ||
| 106 | UnbindCompute(); | ||
| 107 | } | ||
| 108 | |||
| 109 | void ProgramManager::UnbindPipeline() { | ||
| 110 | if (is_pipeline_bound) { | ||
| 111 | is_pipeline_bound = false; | ||
| 112 | glBindProgramPipeline(0); | ||
| 113 | } | ||
| 114 | UnbindCompute(); | ||
| 115 | } | ||
| 116 | |||
| 117 | void ProgramManager::UnbindCompute() { | ||
| 118 | if (is_compute_bound) { | ||
| 119 | is_compute_bound = false; | ||
| 120 | glUseProgram(0); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | } // namespace OpenGL | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index a84f5aeb3..07ffab77f 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h | |||
| @@ -6,8 +6,6 @@ | |||
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include <span> | 7 | #include <span> |
| 8 | 8 | ||
| 9 | #include <glad/glad.h> | ||
| 10 | |||
| 11 | #include "video_core/renderer_opengl/gl_device.h" | 9 | #include "video_core/renderer_opengl/gl_device.h" |
| 12 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 10 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| 13 | 11 | ||
| @@ -16,121 +14,28 @@ namespace OpenGL { | |||
| 16 | class ProgramManager { | 14 | class ProgramManager { |
| 17 | static constexpr size_t NUM_STAGES = 5; | 15 | static constexpr size_t NUM_STAGES = 5; |
| 18 | 16 | ||
| 19 | static constexpr std::array ASSEMBLY_PROGRAM_ENUMS{ | ||
| 20 | GL_VERTEX_PROGRAM_NV, GL_TESS_CONTROL_PROGRAM_NV, GL_TESS_EVALUATION_PROGRAM_NV, | ||
| 21 | GL_GEOMETRY_PROGRAM_NV, GL_FRAGMENT_PROGRAM_NV, | ||
| 22 | }; | ||
| 23 | |||
| 24 | public: | 17 | public: |
| 25 | explicit ProgramManager(const Device& device) { | 18 | explicit ProgramManager(const Device& device); |
| 26 | glCreateProgramPipelines(1, &pipeline.handle); | 19 | |
| 27 | if (device.UseAssemblyShaders()) { | 20 | void BindComputeProgram(GLuint program); |
| 28 | glEnable(GL_COMPUTE_PROGRAM_NV); | 21 | |
| 29 | } | 22 | void BindComputeAssemblyProgram(GLuint program); |
| 30 | } | 23 | |
| 31 | 24 | void BindSourcePrograms(std::span<const OGLProgram, NUM_STAGES> programs); | |
| 32 | void BindComputeProgram(GLuint program) { | 25 | |
| 33 | glUseProgram(program); | 26 | void BindPresentPrograms(GLuint vertex, GLuint fragment); |
| 34 | is_compute_bound = true; | ||
| 35 | } | ||
| 36 | |||
| 37 | void BindComputeAssemblyProgram(GLuint program) { | ||
| 38 | if (current_assembly_compute_program != program) { | ||
| 39 | current_assembly_compute_program = program; | ||
| 40 | glBindProgramARB(GL_COMPUTE_PROGRAM_NV, program); | ||
| 41 | } | ||
| 42 | UnbindPipeline(); | ||
| 43 | } | ||
| 44 | |||
| 45 | void BindSourcePrograms(std::span<const OGLProgram, NUM_STAGES> programs) { | ||
| 46 | static constexpr std::array<GLenum, 5> stage_enums{ | ||
| 47 | GL_VERTEX_SHADER_BIT, GL_TESS_CONTROL_SHADER_BIT, GL_TESS_EVALUATION_SHADER_BIT, | ||
| 48 | GL_GEOMETRY_SHADER_BIT, GL_FRAGMENT_SHADER_BIT, | ||
| 49 | }; | ||
| 50 | for (size_t stage = 0; stage < NUM_STAGES; ++stage) { | ||
| 51 | if (current_programs[stage] != programs[stage].handle) { | ||
| 52 | current_programs[stage] = programs[stage].handle; | ||
| 53 | glUseProgramStages(pipeline.handle, stage_enums[stage], programs[stage].handle); | ||
| 54 | } | ||
| 55 | } | ||
| 56 | BindPipeline(); | ||
| 57 | } | ||
| 58 | |||
| 59 | void BindPresentPrograms(GLuint vertex, GLuint fragment) { | ||
| 60 | if (current_programs[0] != vertex) { | ||
| 61 | current_programs[0] = vertex; | ||
| 62 | glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, vertex); | ||
| 63 | } | ||
| 64 | if (current_programs[4] != fragment) { | ||
| 65 | current_programs[4] = fragment; | ||
| 66 | glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, fragment); | ||
| 67 | } | ||
| 68 | glUseProgramStages( | ||
| 69 | pipeline.handle, | ||
| 70 | GL_TESS_CONTROL_SHADER_BIT | GL_TESS_EVALUATION_SHADER_BIT | GL_GEOMETRY_SHADER_BIT, 0); | ||
| 71 | current_programs[1] = 0; | ||
| 72 | current_programs[2] = 0; | ||
| 73 | current_programs[3] = 0; | ||
| 74 | |||
| 75 | if (current_stage_mask != 0) { | ||
| 76 | current_stage_mask = 0; | ||
| 77 | for (const GLenum program_type : ASSEMBLY_PROGRAM_ENUMS) { | ||
| 78 | glDisable(program_type); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | BindPipeline(); | ||
| 82 | } | ||
| 83 | 27 | ||
| 84 | void BindAssemblyPrograms(std::span<const OGLAssemblyProgram, NUM_STAGES> programs, | 28 | void BindAssemblyPrograms(std::span<const OGLAssemblyProgram, NUM_STAGES> programs, |
| 85 | u32 stage_mask) { | 29 | u32 stage_mask); |
| 86 | const u32 changed_mask = current_stage_mask ^ stage_mask; | 30 | |
| 87 | current_stage_mask = stage_mask; | 31 | void RestoreGuestCompute(); |
| 88 | |||
| 89 | if (changed_mask != 0) { | ||
| 90 | for (size_t stage = 0; stage < NUM_STAGES; ++stage) { | ||
| 91 | if (((changed_mask >> stage) & 1) != 0) { | ||
| 92 | if (((stage_mask >> stage) & 1) != 0) { | ||
| 93 | glEnable(ASSEMBLY_PROGRAM_ENUMS[stage]); | ||
| 94 | } else { | ||
| 95 | glDisable(ASSEMBLY_PROGRAM_ENUMS[stage]); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | } | ||
| 99 | } | ||
| 100 | for (size_t stage = 0; stage < NUM_STAGES; ++stage) { | ||
| 101 | if (current_programs[stage] != programs[stage].handle) { | ||
| 102 | current_programs[stage] = programs[stage].handle; | ||
| 103 | glBindProgramARB(ASSEMBLY_PROGRAM_ENUMS[stage], programs[stage].handle); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | UnbindPipeline(); | ||
| 107 | } | ||
| 108 | |||
| 109 | void RestoreGuestCompute() {} | ||
| 110 | 32 | ||
| 111 | private: | 33 | private: |
| 112 | void BindPipeline() { | 34 | void BindPipeline(); |
| 113 | if (!is_pipeline_bound) { | 35 | |
| 114 | is_pipeline_bound = true; | 36 | void UnbindPipeline(); |
| 115 | glBindProgramPipeline(pipeline.handle); | 37 | |
| 116 | } | 38 | void UnbindCompute(); |
| 117 | UnbindCompute(); | ||
| 118 | } | ||
| 119 | |||
| 120 | void UnbindPipeline() { | ||
| 121 | if (is_pipeline_bound) { | ||
| 122 | is_pipeline_bound = false; | ||
| 123 | glBindProgramPipeline(0); | ||
| 124 | } | ||
| 125 | UnbindCompute(); | ||
| 126 | } | ||
| 127 | |||
| 128 | void UnbindCompute() { | ||
| 129 | if (is_compute_bound) { | ||
| 130 | is_compute_bound = false; | ||
| 131 | glUseProgram(0); | ||
| 132 | } | ||
| 133 | } | ||
| 134 | 39 | ||
| 135 | OGLPipeline pipeline; | 40 | OGLPipeline pipeline; |
| 136 | bool is_pipeline_bound{}; | 41 | bool is_pipeline_bound{}; |
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 3f2b139e0..d728e5c6c 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp | |||
| @@ -4,13 +4,13 @@ | |||
| 4 | #include <algorithm> | 4 | #include <algorithm> |
| 5 | 5 | ||
| 6 | #include "common/settings.h" | 6 | #include "common/settings.h" |
| 7 | #include "video_core/host_shaders/blit_color_float_frag_spv.h" | ||
| 7 | #include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h" | 8 | #include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h" |
| 8 | #include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h" | 9 | #include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h" |
| 9 | #include "video_core/host_shaders/convert_depth_to_float_frag_spv.h" | 10 | #include "video_core/host_shaders/convert_depth_to_float_frag_spv.h" |
| 10 | #include "video_core/host_shaders/convert_float_to_depth_frag_spv.h" | 11 | #include "video_core/host_shaders/convert_float_to_depth_frag_spv.h" |
| 11 | #include "video_core/host_shaders/convert_s8d24_to_abgr8_frag_spv.h" | 12 | #include "video_core/host_shaders/convert_s8d24_to_abgr8_frag_spv.h" |
| 12 | #include "video_core/host_shaders/full_screen_triangle_vert_spv.h" | 13 | #include "video_core/host_shaders/full_screen_triangle_vert_spv.h" |
| 13 | #include "video_core/host_shaders/vulkan_blit_color_float_frag_spv.h" | ||
| 14 | #include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h" | 14 | #include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h" |
| 15 | #include "video_core/renderer_vulkan/blit_image.h" | 15 | #include "video_core/renderer_vulkan/blit_image.h" |
| 16 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" | 16 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" |
| @@ -303,7 +303,7 @@ void UpdateTwoTexturesDescriptorSet(const Device& device, VkDescriptorSet descri | |||
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Region2D& dst_region, | 305 | void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Region2D& dst_region, |
| 306 | const Region2D& src_region) { | 306 | const Region2D& src_region, const Extent3D& src_size = {1, 1, 1}) { |
| 307 | const VkOffset2D offset{ | 307 | const VkOffset2D offset{ |
| 308 | .x = std::min(dst_region.start.x, dst_region.end.x), | 308 | .x = std::min(dst_region.start.x, dst_region.end.x), |
| 309 | .y = std::min(dst_region.start.y, dst_region.end.y), | 309 | .y = std::min(dst_region.start.y, dst_region.end.y), |
| @@ -325,12 +325,15 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Regi | |||
| 325 | .offset = offset, | 325 | .offset = offset, |
| 326 | .extent = extent, | 326 | .extent = extent, |
| 327 | }; | 327 | }; |
| 328 | const float scale_x = static_cast<float>(src_region.end.x - src_region.start.x); | 328 | const float scale_x = static_cast<float>(src_region.end.x - src_region.start.x) / |
| 329 | const float scale_y = static_cast<float>(src_region.end.y - src_region.start.y); | 329 | static_cast<float>(src_size.width); |
| 330 | const float scale_y = static_cast<float>(src_region.end.y - src_region.start.y) / | ||
| 331 | static_cast<float>(src_size.height); | ||
| 330 | const PushConstants push_constants{ | 332 | const PushConstants push_constants{ |
| 331 | .tex_scale = {scale_x, scale_y}, | 333 | .tex_scale = {scale_x, scale_y}, |
| 332 | .tex_offset = {static_cast<float>(src_region.start.x), | 334 | .tex_offset = {static_cast<float>(src_region.start.x) / static_cast<float>(src_size.width), |
| 333 | static_cast<float>(src_region.start.y)}, | 335 | static_cast<float>(src_region.start.y) / |
| 336 | static_cast<float>(src_size.height)}, | ||
| 334 | }; | 337 | }; |
| 335 | cmdbuf.SetViewport(0, viewport); | 338 | cmdbuf.SetViewport(0, viewport); |
| 336 | cmdbuf.SetScissor(0, scissor); | 339 | cmdbuf.SetScissor(0, scissor); |
| @@ -365,7 +368,7 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_, | |||
| 365 | two_textures_pipeline_layout(device.GetLogical().CreatePipelineLayout( | 368 | two_textures_pipeline_layout(device.GetLogical().CreatePipelineLayout( |
| 366 | PipelineLayoutCreateInfo(two_textures_set_layout.address()))), | 369 | PipelineLayoutCreateInfo(two_textures_set_layout.address()))), |
| 367 | full_screen_vert(BuildShader(device, FULL_SCREEN_TRIANGLE_VERT_SPV)), | 370 | full_screen_vert(BuildShader(device, FULL_SCREEN_TRIANGLE_VERT_SPV)), |
| 368 | blit_color_to_color_frag(BuildShader(device, VULKAN_BLIT_COLOR_FLOAT_FRAG_SPV)), | 371 | blit_color_to_color_frag(BuildShader(device, BLIT_COLOR_FLOAT_FRAG_SPV)), |
| 369 | blit_depth_stencil_frag(BuildShader(device, VULKAN_BLIT_DEPTH_STENCIL_FRAG_SPV)), | 372 | blit_depth_stencil_frag(BuildShader(device, VULKAN_BLIT_DEPTH_STENCIL_FRAG_SPV)), |
| 370 | convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)), | 373 | convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)), |
| 371 | convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)), | 374 | convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)), |
| @@ -404,6 +407,30 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView | |||
| 404 | scheduler.InvalidateState(); | 407 | scheduler.InvalidateState(); |
| 405 | } | 408 | } |
| 406 | 409 | ||
| 410 | void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView src_image_view, | ||
| 411 | VkSampler src_sampler, const Region2D& dst_region, | ||
| 412 | const Region2D& src_region, const Extent3D& src_size) { | ||
| 413 | const BlitImagePipelineKey key{ | ||
| 414 | .renderpass = dst_framebuffer->RenderPass(), | ||
| 415 | .operation = Tegra::Engines::Fermi2D::Operation::SrcCopy, | ||
| 416 | }; | ||
| 417 | const VkPipelineLayout layout = *one_texture_pipeline_layout; | ||
| 418 | const VkPipeline pipeline = FindOrEmplaceColorPipeline(key); | ||
| 419 | scheduler.RequestRenderpass(dst_framebuffer); | ||
| 420 | scheduler.Record([this, dst_region, src_region, src_size, pipeline, layout, src_sampler, | ||
| 421 | src_image_view](vk::CommandBuffer cmdbuf) { | ||
| 422 | // TODO: Barriers | ||
| 423 | const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit(); | ||
| 424 | UpdateOneTextureDescriptorSet(device, descriptor_set, src_sampler, src_image_view); | ||
| 425 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); | ||
| 426 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, | ||
| 427 | nullptr); | ||
| 428 | BindBlitState(cmdbuf, layout, dst_region, src_region, src_size); | ||
| 429 | cmdbuf.Draw(3, 1, 0, 0); | ||
| 430 | }); | ||
| 431 | scheduler.InvalidateState(); | ||
| 432 | } | ||
| 433 | |||
| 407 | void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, | 434 | void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, |
| 408 | VkImageView src_depth_view, VkImageView src_stencil_view, | 435 | VkImageView src_depth_view, VkImageView src_stencil_view, |
| 409 | const Region2D& dst_region, const Region2D& src_region, | 436 | const Region2D& dst_region, const Region2D& src_region, |
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index 5df679fb4..e2db33f56 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h | |||
| @@ -10,6 +10,8 @@ | |||
| 10 | 10 | ||
| 11 | namespace Vulkan { | 11 | namespace Vulkan { |
| 12 | 12 | ||
| 13 | using VideoCommon::Extent3D; | ||
| 14 | using VideoCommon::Offset2D; | ||
| 13 | using VideoCommon::Region2D; | 15 | using VideoCommon::Region2D; |
| 14 | 16 | ||
| 15 | class Device; | 17 | class Device; |
| @@ -36,6 +38,10 @@ public: | |||
| 36 | Tegra::Engines::Fermi2D::Filter filter, | 38 | Tegra::Engines::Fermi2D::Filter filter, |
| 37 | Tegra::Engines::Fermi2D::Operation operation); | 39 | Tegra::Engines::Fermi2D::Operation operation); |
| 38 | 40 | ||
| 41 | void BlitColor(const Framebuffer* dst_framebuffer, VkImageView src_image_view, | ||
| 42 | VkSampler src_sampler, const Region2D& dst_region, const Region2D& src_region, | ||
| 43 | const Extent3D& src_size); | ||
| 44 | |||
| 39 | void BlitDepthStencil(const Framebuffer* dst_framebuffer, VkImageView src_depth_view, | 45 | void BlitDepthStencil(const Framebuffer* dst_framebuffer, VkImageView src_depth_view, |
| 40 | VkImageView src_stencil_view, const Region2D& dst_region, | 46 | VkImageView src_stencil_view, const Region2D& dst_region, |
| 41 | const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, | 47 | const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 242bf9602..153096fa4 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -265,6 +265,34 @@ void RasterizerVulkan::DrawIndirect() { | |||
| 265 | buffer_cache.SetDrawIndirect(nullptr); | 265 | buffer_cache.SetDrawIndirect(nullptr); |
| 266 | } | 266 | } |
| 267 | 267 | ||
| 268 | void RasterizerVulkan::DrawTexture() { | ||
| 269 | MICROPROFILE_SCOPE(Vulkan_Drawing); | ||
| 270 | |||
| 271 | SCOPE_EXIT({ gpu.TickWork(); }); | ||
| 272 | FlushWork(); | ||
| 273 | |||
| 274 | query_cache.UpdateCounters(); | ||
| 275 | |||
| 276 | texture_cache.SynchronizeGraphicsDescriptors(); | ||
| 277 | texture_cache.UpdateRenderTargets(false); | ||
| 278 | |||
| 279 | UpdateDynamicStates(); | ||
| 280 | |||
| 281 | const auto& draw_texture_state = maxwell3d->draw_manager->GetDrawTextureState(); | ||
| 282 | const auto& sampler = texture_cache.GetGraphicsSampler(draw_texture_state.src_sampler); | ||
| 283 | const auto& texture = texture_cache.GetImageView(draw_texture_state.src_texture); | ||
| 284 | Region2D dst_region = {Offset2D{.x = static_cast<s32>(draw_texture_state.dst_x0), | ||
| 285 | .y = static_cast<s32>(draw_texture_state.dst_y0)}, | ||
| 286 | Offset2D{.x = static_cast<s32>(draw_texture_state.dst_x1), | ||
| 287 | .y = static_cast<s32>(draw_texture_state.dst_y1)}}; | ||
| 288 | Region2D src_region = {Offset2D{.x = static_cast<s32>(draw_texture_state.src_x0), | ||
| 289 | .y = static_cast<s32>(draw_texture_state.src_y0)}, | ||
| 290 | Offset2D{.x = static_cast<s32>(draw_texture_state.src_x1), | ||
| 291 | .y = static_cast<s32>(draw_texture_state.src_y1)}}; | ||
| 292 | blit_image.BlitColor(texture_cache.GetFramebuffer(), texture.RenderTarget(), sampler->Handle(), | ||
| 293 | dst_region, src_region, texture.size); | ||
| 294 | } | ||
| 295 | |||
| 268 | void RasterizerVulkan::Clear(u32 layer_count) { | 296 | void RasterizerVulkan::Clear(u32 layer_count) { |
| 269 | MICROPROFILE_SCOPE(Vulkan_Clearing); | 297 | MICROPROFILE_SCOPE(Vulkan_Clearing); |
| 270 | 298 | ||
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index c661e5b19..deb44dcaa 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -66,6 +66,7 @@ public: | |||
| 66 | 66 | ||
| 67 | void Draw(bool is_indexed, u32 instance_count) override; | 67 | void Draw(bool is_indexed, u32 instance_count) override; |
| 68 | void DrawIndirect() override; | 68 | void DrawIndirect() override; |
| 69 | void DrawTexture() override; | ||
| 69 | void Clear(u32 layer_count) override; | 70 | void Clear(u32 layer_count) override; |
| 70 | void DispatchCompute() override; | 71 | void DispatchCompute() override; |
| 71 | void ResetCounter(VideoCore::QueryType type) override; | 72 | void ResetCounter(VideoCore::QueryType type) override; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 87152c8e9..1b01990a4 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -149,6 +149,13 @@ typename P::ImageView& TextureCache<P>::GetImageView(ImageViewId id) noexcept { | |||
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | template <class P> | 151 | template <class P> |
| 152 | typename P::ImageView& TextureCache<P>::GetImageView(u32 index) noexcept { | ||
| 153 | const auto image_view_id = VisitImageView(channel_state->graphics_image_table, | ||
| 154 | channel_state->graphics_image_view_ids, index); | ||
| 155 | return slot_image_views[image_view_id]; | ||
| 156 | } | ||
| 157 | |||
| 158 | template <class P> | ||
| 152 | void TextureCache<P>::MarkModification(ImageId id) noexcept { | 159 | void TextureCache<P>::MarkModification(ImageId id) noexcept { |
| 153 | MarkModification(slot_images[id]); | 160 | MarkModification(slot_images[id]); |
| 154 | } | 161 | } |
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 4eea1f609..485eaabaa 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h | |||
| @@ -129,6 +129,9 @@ public: | |||
| 129 | /// Return a reference to the given image view id | 129 | /// Return a reference to the given image view id |
| 130 | [[nodiscard]] ImageView& GetImageView(ImageViewId id) noexcept; | 130 | [[nodiscard]] ImageView& GetImageView(ImageViewId id) noexcept; |
| 131 | 131 | ||
| 132 | /// Get the imageview from the graphics descriptor table in the specified index | ||
| 133 | [[nodiscard]] ImageView& GetImageView(u32 index) noexcept; | ||
| 134 | |||
| 132 | /// Mark an image as modified from the GPU | 135 | /// Mark an image as modified from the GPU |
| 133 | void MarkModification(ImageId id) noexcept; | 136 | void MarkModification(ImageId id) noexcept; |
| 134 | 137 | ||