summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/host_shaders/CMakeLists.txt2
-rw-r--r--src/video_core/host_shaders/full_screen_triangle.vert15
-rw-r--r--src/video_core/host_shaders/vulkan_blit_color_float.frag13
-rw-r--r--src/video_core/rasterizer_interface.h3
-rw-r--r--src/video_core/renderer_null/null_rasterizer.cpp1
-rw-r--r--src/video_core/renderer_null/null_rasterizer.h1
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp1
-rw-r--r--src/video_core/renderer_opengl/gl_device.h7
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp44
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h4
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.cpp121
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.h129
-rw-r--r--src/video_core/renderer_vulkan/blit_image.cpp41
-rw-r--r--src/video_core/renderer_vulkan/blit_image.h6
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp28
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h1
-rw-r--r--src/video_core/texture_cache/texture_cache.h7
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h3
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
12set(SHADER_FILES 12set(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
18out gl_PerVertex {
19 vec4 gl_Position;
20};
14#endif 21#endif
15 22
16BEGIN_PUSH_CONSTANTS 23BEGIN_PUSH_CONSTANTS
@@ -21,8 +28,8 @@ END_PUSH_CONSTANTS
21layout(location = 0) out vec2 texcoord; 28layout(location = 0) out vec2 texcoord;
22 29
23void main() { 30void 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
6layout(binding = 0) uniform sampler2D tex;
7
8layout(location = 0) in vec2 texcoord;
9layout(location = 0) out vec4 color;
10
11void 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
21RasterizerNull::~RasterizerNull() = default; 21RasterizerNull::~RasterizerNull() = default;
22 22
23void RasterizerNull::Draw(bool is_indexed, u32 instance_count) {} 23void RasterizerNull::Draw(bool is_indexed, u32 instance_count) {}
24void RasterizerNull::DrawTexture() {}
24void RasterizerNull::Clear(u32 layer_count) {} 25void RasterizerNull::Clear(u32 layer_count) {}
25void RasterizerNull::DispatchCompute() {} 26void RasterizerNull::DispatchCompute() {}
26void RasterizerNull::ResetCounter(VideoCore::QueryType type) {} 27void 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
69RasterizerOpenGL::~RasterizerOpenGL() = default; 70RasterizerOpenGL::~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
322void 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
321void RasterizerOpenGL::DispatchCompute() { 363void 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
8namespace OpenGL {
9
10static 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
15ProgramManager::ProgramManager(const Device& device) {
16 glCreateProgramPipelines(1, &pipeline.handle);
17 if (device.UseAssemblyShaders()) {
18 glEnable(GL_COMPUTE_PROGRAM_NV);
19 }
20}
21
22void ProgramManager::BindComputeProgram(GLuint program) {
23 glUseProgram(program);
24 is_compute_bound = true;
25}
26
27void 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
35void 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
49void 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
74void 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
99void ProgramManager::RestoreGuestCompute() {}
100
101void ProgramManager::BindPipeline() {
102 if (!is_pipeline_bound) {
103 is_pipeline_bound = true;
104 glBindProgramPipeline(pipeline.handle);
105 }
106 UnbindCompute();
107}
108
109void ProgramManager::UnbindPipeline() {
110 if (is_pipeline_bound) {
111 is_pipeline_bound = false;
112 glBindProgramPipeline(0);
113 }
114 UnbindCompute();
115}
116
117void 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 {
16class ProgramManager { 14class 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
24public: 17public:
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
111private: 33private:
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
305void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Region2D& dst_region, 305void 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
410void 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
407void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, 434void 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
11namespace Vulkan { 11namespace Vulkan {
12 12
13using VideoCommon::Extent3D;
14using VideoCommon::Offset2D;
13using VideoCommon::Region2D; 15using VideoCommon::Region2D;
14 16
15class Device; 17class 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
268void 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
268void RasterizerVulkan::Clear(u32 layer_count) { 296void 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
151template <class P> 151template <class P>
152typename 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
158template <class P>
152void TextureCache<P>::MarkModification(ImageId id) noexcept { 159void 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