diff options
Diffstat (limited to 'src')
40 files changed, 365 insertions, 238 deletions
diff --git a/src/common/color.h b/src/common/color.h index 381d6332e..bbcac858e 100644 --- a/src/common/color.h +++ b/src/common/color.h | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include "common/swap.h" | 10 | #include "common/swap.h" |
| 11 | #include "common/vector_math.h" | 11 | #include "common/vector_math.h" |
| 12 | 12 | ||
| 13 | namespace Color { | 13 | namespace Common::Color { |
| 14 | 14 | ||
| 15 | /// Convert a 1-bit color component to 8 bit | 15 | /// Convert a 1-bit color component to 8 bit |
| 16 | [[nodiscard]] constexpr u8 Convert1To8(u8 value) { | 16 | [[nodiscard]] constexpr u8 Convert1To8(u8 value) { |
| @@ -268,4 +268,4 @@ inline void EncodeX24S8(u8 stencil, u8* bytes) { | |||
| 268 | bytes[3] = stencil; | 268 | bytes[3] = stencil; |
| 269 | } | 269 | } |
| 270 | 270 | ||
| 271 | } // namespace Color | 271 | } // namespace Common::Color |
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 358943429..ef0bae556 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp | |||
| @@ -41,9 +41,9 @@ void CpuManager::Shutdown() { | |||
| 41 | running_mode = false; | 41 | running_mode = false; |
| 42 | Pause(false); | 42 | Pause(false); |
| 43 | if (is_multicore) { | 43 | if (is_multicore) { |
| 44 | for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { | 44 | for (auto& data : core_data) { |
| 45 | core_data[core].host_thread->join(); | 45 | data.host_thread->join(); |
| 46 | core_data[core].host_thread.reset(); | 46 | data.host_thread.reset(); |
| 47 | } | 47 | } |
| 48 | } else { | 48 | } else { |
| 49 | core_data[0].host_thread->join(); | 49 | core_data[0].host_thread->join(); |
| @@ -166,25 +166,23 @@ void CpuManager::MultiCorePause(bool paused) { | |||
| 166 | bool all_not_barrier = false; | 166 | bool all_not_barrier = false; |
| 167 | while (!all_not_barrier) { | 167 | while (!all_not_barrier) { |
| 168 | all_not_barrier = true; | 168 | all_not_barrier = true; |
| 169 | for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { | 169 | for (const auto& data : core_data) { |
| 170 | all_not_barrier &= | 170 | all_not_barrier &= !data.is_running.load() && data.initialized.load(); |
| 171 | !core_data[core].is_running.load() && core_data[core].initialized.load(); | ||
| 172 | } | 171 | } |
| 173 | } | 172 | } |
| 174 | for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { | 173 | for (auto& data : core_data) { |
| 175 | core_data[core].enter_barrier->Set(); | 174 | data.enter_barrier->Set(); |
| 176 | } | 175 | } |
| 177 | if (paused_state.load()) { | 176 | if (paused_state.load()) { |
| 178 | bool all_barrier = false; | 177 | bool all_barrier = false; |
| 179 | while (!all_barrier) { | 178 | while (!all_barrier) { |
| 180 | all_barrier = true; | 179 | all_barrier = true; |
| 181 | for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { | 180 | for (const auto& data : core_data) { |
| 182 | all_barrier &= | 181 | all_barrier &= data.is_paused.load() && data.initialized.load(); |
| 183 | core_data[core].is_paused.load() && core_data[core].initialized.load(); | ||
| 184 | } | 182 | } |
| 185 | } | 183 | } |
| 186 | for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { | 184 | for (auto& data : core_data) { |
| 187 | core_data[core].exit_barrier->Set(); | 185 | data.exit_barrier->Set(); |
| 188 | } | 186 | } |
| 189 | } | 187 | } |
| 190 | } else { | 188 | } else { |
| @@ -192,9 +190,8 @@ void CpuManager::MultiCorePause(bool paused) { | |||
| 192 | bool all_barrier = false; | 190 | bool all_barrier = false; |
| 193 | while (!all_barrier) { | 191 | while (!all_barrier) { |
| 194 | all_barrier = true; | 192 | all_barrier = true; |
| 195 | for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { | 193 | for (const auto& data : core_data) { |
| 196 | all_barrier &= | 194 | all_barrier &= data.is_paused.load() && data.initialized.load(); |
| 197 | core_data[core].is_paused.load() && core_data[core].initialized.load(); | ||
| 198 | } | 195 | } |
| 199 | } | 196 | } |
| 200 | /// Don't release the barrier | 197 | /// Don't release the barrier |
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index e42b677f7..da01002d5 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp | |||
| @@ -257,8 +257,7 @@ std::vector<NcaID> PlaceholderCache::List() const { | |||
| 257 | for (const auto& sdir : dir->GetSubdirectories()) { | 257 | for (const auto& sdir : dir->GetSubdirectories()) { |
| 258 | for (const auto& file : sdir->GetFiles()) { | 258 | for (const auto& file : sdir->GetFiles()) { |
| 259 | const auto name = file->GetName(); | 259 | const auto name = file->GetName(); |
| 260 | if (name.length() == 36 && name[32] == '.' && name[33] == 'n' && name[34] == 'c' && | 260 | if (name.length() == 36 && name.ends_with(".nca")) { |
| 261 | name[35] == 'a') { | ||
| 262 | out.push_back(Common::HexStringToArray<0x10>(name.substr(0, 32))); | 261 | out.push_back(Common::HexStringToArray<0x10>(name.substr(0, 32))); |
| 263 | } | 262 | } |
| 264 | } | 263 | } |
| @@ -621,25 +620,25 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex | |||
| 621 | 620 | ||
| 622 | InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type, | 621 | InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type, |
| 623 | bool overwrite_if_exists, const VfsCopyFunction& copy) { | 622 | bool overwrite_if_exists, const VfsCopyFunction& copy) { |
| 624 | CNMTHeader header{ | 623 | const CNMTHeader header{ |
| 625 | nca.GetTitleId(), // Title ID | 624 | .title_id = nca.GetTitleId(), |
| 626 | 0, // Ignore/Default title version | 625 | .title_version = 0, |
| 627 | type, // Type | 626 | .type = type, |
| 628 | {}, // Padding | 627 | .reserved = {}, |
| 629 | 0x10, // Default table offset | 628 | .table_offset = 0x10, |
| 630 | 1, // 1 Content Entry | 629 | .number_content_entries = 1, |
| 631 | 0, // No Meta Entries | 630 | .number_meta_entries = 0, |
| 632 | {}, // Padding | 631 | .attributes = 0, |
| 633 | {}, // Reserved 1 | 632 | .reserved2 = {}, |
| 634 | 0, // Is committed | 633 | .is_committed = 0, |
| 635 | 0, // Required download system version | 634 | .required_download_system_version = 0, |
| 636 | {}, // Reserved 2 | 635 | .reserved3 = {}, |
| 637 | }; | 636 | }; |
| 638 | OptionalHeader opt_header{0, 0}; | 637 | const OptionalHeader opt_header{0, 0}; |
| 639 | ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}}; | 638 | ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}}; |
| 640 | const auto& data = nca.GetBaseFile()->ReadBytes(0x100000); | 639 | const auto& data = nca.GetBaseFile()->ReadBytes(0x100000); |
| 641 | mbedtls_sha256_ret(data.data(), data.size(), c_rec.hash.data(), 0); | 640 | mbedtls_sha256_ret(data.data(), data.size(), c_rec.hash.data(), 0); |
| 642 | memcpy(&c_rec.nca_id, &c_rec.hash, 16); | 641 | std::memcpy(&c_rec.nca_id, &c_rec.hash, 16); |
| 643 | const CNMT new_cnmt(header, opt_header, {c_rec}, {}); | 642 | const CNMT new_cnmt(header, opt_header, {c_rec}, {}); |
| 644 | if (!RawInstallYuzuMeta(new_cnmt)) { | 643 | if (!RawInstallYuzuMeta(new_cnmt)) { |
| 645 | return InstallResult::ErrorMetaFailed; | 644 | return InstallResult::ErrorMetaFailed; |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 3cd896a0f..d85f1e9d1 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | add_subdirectory(host_shaders) | ||
| 2 | |||
| 1 | add_library(video_core STATIC | 3 | add_library(video_core STATIC |
| 2 | buffer_cache/buffer_block.h | 4 | buffer_cache/buffer_block.h |
| 3 | buffer_cache/buffer_cache.h | 5 | buffer_cache/buffer_cache.h |
| @@ -244,6 +246,9 @@ create_target_directory_groups(video_core) | |||
| 244 | target_link_libraries(video_core PUBLIC common core) | 246 | target_link_libraries(video_core PUBLIC common core) |
| 245 | target_link_libraries(video_core PRIVATE glad xbyak) | 247 | target_link_libraries(video_core PRIVATE glad xbyak) |
| 246 | 248 | ||
| 249 | add_dependencies(video_core host_shaders) | ||
| 250 | target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) | ||
| 251 | |||
| 247 | if (ENABLE_VULKAN) | 252 | if (ENABLE_VULKAN) |
| 248 | target_include_directories(video_core PRIVATE sirit ../../externals/Vulkan-Headers/include) | 253 | target_include_directories(video_core PRIVATE sirit ../../externals/Vulkan-Headers/include) |
| 249 | target_compile_definitions(video_core PRIVATE HAS_VULKAN) | 254 | target_compile_definitions(video_core PRIVATE HAS_VULKAN) |
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index ff10ff40d..6e50661a3 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp | |||
| @@ -10,7 +10,13 @@ | |||
| 10 | 10 | ||
| 11 | namespace Tegra::Engines { | 11 | namespace Tegra::Engines { |
| 12 | 12 | ||
| 13 | Fermi2D::Fermi2D(VideoCore::RasterizerInterface& rasterizer) : rasterizer{rasterizer} {} | 13 | Fermi2D::Fermi2D() = default; |
| 14 | |||
| 15 | Fermi2D::~Fermi2D() = default; | ||
| 16 | |||
| 17 | void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { | ||
| 18 | rasterizer = &rasterizer_; | ||
| 19 | } | ||
| 14 | 20 | ||
| 15 | void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | 21 | void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { |
| 16 | ASSERT_MSG(method < Regs::NUM_REGS, | 22 | ASSERT_MSG(method < Regs::NUM_REGS, |
| @@ -87,7 +93,7 @@ void Fermi2D::HandleSurfaceCopy() { | |||
| 87 | copy_config.src_rect = src_rect; | 93 | copy_config.src_rect = src_rect; |
| 88 | copy_config.dst_rect = dst_rect; | 94 | copy_config.dst_rect = dst_rect; |
| 89 | 95 | ||
| 90 | if (!rasterizer.AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) { | 96 | if (!rasterizer->AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) { |
| 91 | UNIMPLEMENTED(); | 97 | UNIMPLEMENTED(); |
| 92 | } | 98 | } |
| 93 | } | 99 | } |
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h index 8f37d053f..213abfaae 100644 --- a/src/video_core/engines/fermi_2d.h +++ b/src/video_core/engines/fermi_2d.h | |||
| @@ -34,8 +34,11 @@ namespace Tegra::Engines { | |||
| 34 | 34 | ||
| 35 | class Fermi2D final : public EngineInterface { | 35 | class Fermi2D final : public EngineInterface { |
| 36 | public: | 36 | public: |
| 37 | explicit Fermi2D(VideoCore::RasterizerInterface& rasterizer); | 37 | explicit Fermi2D(); |
| 38 | ~Fermi2D() = default; | 38 | ~Fermi2D(); |
| 39 | |||
| 40 | /// Binds a rasterizer to this engine. | ||
| 41 | void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); | ||
| 39 | 42 | ||
| 40 | /// Write the value to the register identified by method. | 43 | /// Write the value to the register identified by method. |
| 41 | void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; | 44 | void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; |
| @@ -149,7 +152,7 @@ public: | |||
| 149 | }; | 152 | }; |
| 150 | 153 | ||
| 151 | private: | 154 | private: |
| 152 | VideoCore::RasterizerInterface& rasterizer; | 155 | VideoCore::RasterizerInterface* rasterizer; |
| 153 | 156 | ||
| 154 | /// Performs the copy from the source surface to the destination surface as configured in the | 157 | /// Performs the copy from the source surface to the destination surface as configured in the |
| 155 | /// registers. | 158 | /// registers. |
diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp index a82b06a38..898370739 100644 --- a/src/video_core/engines/kepler_compute.cpp +++ b/src/video_core/engines/kepler_compute.cpp | |||
| @@ -16,14 +16,15 @@ | |||
| 16 | 16 | ||
| 17 | namespace Tegra::Engines { | 17 | namespace Tegra::Engines { |
| 18 | 18 | ||
| 19 | KeplerCompute::KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | 19 | KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manager_) |
| 20 | MemoryManager& memory_manager) | 20 | : system{system_}, memory_manager{memory_manager_}, upload_state{memory_manager, regs.upload} {} |
| 21 | : system{system}, rasterizer{rasterizer}, memory_manager{memory_manager}, upload_state{ | ||
| 22 | memory_manager, | ||
| 23 | regs.upload} {} | ||
| 24 | 21 | ||
| 25 | KeplerCompute::~KeplerCompute() = default; | 22 | KeplerCompute::~KeplerCompute() = default; |
| 26 | 23 | ||
| 24 | void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { | ||
| 25 | rasterizer = &rasterizer_; | ||
| 26 | } | ||
| 27 | |||
| 27 | void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | 28 | void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) { |
| 28 | ASSERT_MSG(method < Regs::NUM_REGS, | 29 | ASSERT_MSG(method < Regs::NUM_REGS, |
| 29 | "Invalid KeplerCompute register, increase the size of the Regs structure"); | 30 | "Invalid KeplerCompute register, increase the size of the Regs structure"); |
| @@ -104,11 +105,11 @@ SamplerDescriptor KeplerCompute::AccessSampler(u32 handle) const { | |||
| 104 | } | 105 | } |
| 105 | 106 | ||
| 106 | VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() { | 107 | VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() { |
| 107 | return rasterizer.AccessGuestDriverProfile(); | 108 | return rasterizer->AccessGuestDriverProfile(); |
| 108 | } | 109 | } |
| 109 | 110 | ||
| 110 | const VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() const { | 111 | const VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() const { |
| 111 | return rasterizer.AccessGuestDriverProfile(); | 112 | return rasterizer->AccessGuestDriverProfile(); |
| 112 | } | 113 | } |
| 113 | 114 | ||
| 114 | void KeplerCompute::ProcessLaunch() { | 115 | void KeplerCompute::ProcessLaunch() { |
| @@ -119,7 +120,7 @@ void KeplerCompute::ProcessLaunch() { | |||
| 119 | const GPUVAddr code_addr = regs.code_loc.Address() + launch_description.program_start; | 120 | const GPUVAddr code_addr = regs.code_loc.Address() + launch_description.program_start; |
| 120 | LOG_TRACE(HW_GPU, "Compute invocation launched at address 0x{:016x}", code_addr); | 121 | LOG_TRACE(HW_GPU, "Compute invocation launched at address 0x{:016x}", code_addr); |
| 121 | 122 | ||
| 122 | rasterizer.DispatchCompute(code_addr); | 123 | rasterizer->DispatchCompute(code_addr); |
| 123 | } | 124 | } |
| 124 | 125 | ||
| 125 | Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const { | 126 | Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const { |
diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h index b7f668d88..7f2500aab 100644 --- a/src/video_core/engines/kepler_compute.h +++ b/src/video_core/engines/kepler_compute.h | |||
| @@ -42,10 +42,12 @@ namespace Tegra::Engines { | |||
| 42 | 42 | ||
| 43 | class KeplerCompute final : public ConstBufferEngineInterface, public EngineInterface { | 43 | class KeplerCompute final : public ConstBufferEngineInterface, public EngineInterface { |
| 44 | public: | 44 | public: |
| 45 | explicit KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | 45 | explicit KeplerCompute(Core::System& system, MemoryManager& memory_manager); |
| 46 | MemoryManager& memory_manager); | ||
| 47 | ~KeplerCompute(); | 46 | ~KeplerCompute(); |
| 48 | 47 | ||
| 48 | /// Binds a rasterizer to this engine. | ||
| 49 | void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); | ||
| 50 | |||
| 49 | static constexpr std::size_t NumConstBuffers = 8; | 51 | static constexpr std::size_t NumConstBuffers = 8; |
| 50 | 52 | ||
| 51 | struct Regs { | 53 | struct Regs { |
| @@ -230,11 +232,6 @@ public: | |||
| 230 | const VideoCore::GuestDriverProfile& AccessGuestDriverProfile() const override; | 232 | const VideoCore::GuestDriverProfile& AccessGuestDriverProfile() const override; |
| 231 | 233 | ||
| 232 | private: | 234 | private: |
| 233 | Core::System& system; | ||
| 234 | VideoCore::RasterizerInterface& rasterizer; | ||
| 235 | MemoryManager& memory_manager; | ||
| 236 | Upload::State upload_state; | ||
| 237 | |||
| 238 | void ProcessLaunch(); | 235 | void ProcessLaunch(); |
| 239 | 236 | ||
| 240 | /// Retrieves information about a specific TIC entry from the TIC buffer. | 237 | /// Retrieves information about a specific TIC entry from the TIC buffer. |
| @@ -242,6 +239,11 @@ private: | |||
| 242 | 239 | ||
| 243 | /// Retrieves information about a specific TSC entry from the TSC buffer. | 240 | /// Retrieves information about a specific TSC entry from the TSC buffer. |
| 244 | Texture::TSCEntry GetTSCEntry(u32 tsc_index) const; | 241 | Texture::TSCEntry GetTSCEntry(u32 tsc_index) const; |
| 242 | |||
| 243 | Core::System& system; | ||
| 244 | MemoryManager& memory_manager; | ||
| 245 | VideoCore::RasterizerInterface* rasterizer = nullptr; | ||
| 246 | Upload::State upload_state; | ||
| 245 | }; | 247 | }; |
| 246 | 248 | ||
| 247 | #define ASSERT_REG_POSITION(field_name, position) \ | 249 | #define ASSERT_REG_POSITION(field_name, position) \ |
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index c01436295..33854445f 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -22,14 +22,19 @@ using VideoCore::QueryType; | |||
| 22 | /// First register id that is actually a Macro call. | 22 | /// First register id that is actually a Macro call. |
| 23 | constexpr u32 MacroRegistersStart = 0xE00; | 23 | constexpr u32 MacroRegistersStart = 0xE00; |
| 24 | 24 | ||
| 25 | Maxwell3D::Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | 25 | Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_) |
| 26 | MemoryManager& memory_manager) | 26 | : system{system_}, memory_manager{memory_manager_}, macro_engine{GetMacroEngine(*this)}, |
| 27 | : system{system}, rasterizer{rasterizer}, memory_manager{memory_manager}, | 27 | upload_state{memory_manager, regs.upload} { |
| 28 | macro_engine{GetMacroEngine(*this)}, upload_state{memory_manager, regs.upload} { | ||
| 29 | dirty.flags.flip(); | 28 | dirty.flags.flip(); |
| 30 | InitializeRegisterDefaults(); | 29 | InitializeRegisterDefaults(); |
| 31 | } | 30 | } |
| 32 | 31 | ||
| 32 | Maxwell3D::~Maxwell3D() = default; | ||
| 33 | |||
| 34 | void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { | ||
| 35 | rasterizer = &rasterizer_; | ||
| 36 | } | ||
| 37 | |||
| 33 | void Maxwell3D::InitializeRegisterDefaults() { | 38 | void Maxwell3D::InitializeRegisterDefaults() { |
| 34 | // Initializes registers to their default values - what games expect them to be at boot. This is | 39 | // Initializes registers to their default values - what games expect them to be at boot. This is |
| 35 | // for certain registers that may not be explicitly set by games. | 40 | // for certain registers that may not be explicitly set by games. |
| @@ -192,7 +197,7 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | |||
| 192 | 197 | ||
| 193 | switch (method) { | 198 | switch (method) { |
| 194 | case MAXWELL3D_REG_INDEX(wait_for_idle): { | 199 | case MAXWELL3D_REG_INDEX(wait_for_idle): { |
| 195 | rasterizer.WaitForIdle(); | 200 | rasterizer->WaitForIdle(); |
| 196 | break; | 201 | break; |
| 197 | } | 202 | } |
| 198 | case MAXWELL3D_REG_INDEX(shadow_ram_control): { | 203 | case MAXWELL3D_REG_INDEX(shadow_ram_control): { |
| @@ -402,7 +407,7 @@ void Maxwell3D::FlushMMEInlineDraw() { | |||
| 402 | 407 | ||
| 403 | const bool is_indexed = mme_draw.current_mode == MMEDrawMode::Indexed; | 408 | const bool is_indexed = mme_draw.current_mode == MMEDrawMode::Indexed; |
| 404 | if (ShouldExecute()) { | 409 | if (ShouldExecute()) { |
| 405 | rasterizer.Draw(is_indexed, true); | 410 | rasterizer->Draw(is_indexed, true); |
| 406 | } | 411 | } |
| 407 | 412 | ||
| 408 | // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if | 413 | // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if |
| @@ -465,7 +470,7 @@ void Maxwell3D::ProcessQueryGet() { | |||
| 465 | switch (regs.query.query_get.operation) { | 470 | switch (regs.query.query_get.operation) { |
| 466 | case Regs::QueryOperation::Release: | 471 | case Regs::QueryOperation::Release: |
| 467 | if (regs.query.query_get.fence == 1) { | 472 | if (regs.query.query_get.fence == 1) { |
| 468 | rasterizer.SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence); | 473 | rasterizer->SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence); |
| 469 | } else { | 474 | } else { |
| 470 | StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0); | 475 | StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0); |
| 471 | } | 476 | } |
| @@ -533,7 +538,7 @@ void Maxwell3D::ProcessQueryCondition() { | |||
| 533 | void Maxwell3D::ProcessCounterReset() { | 538 | void Maxwell3D::ProcessCounterReset() { |
| 534 | switch (regs.counter_reset) { | 539 | switch (regs.counter_reset) { |
| 535 | case Regs::CounterReset::SampleCnt: | 540 | case Regs::CounterReset::SampleCnt: |
| 536 | rasterizer.ResetCounter(QueryType::SamplesPassed); | 541 | rasterizer->ResetCounter(QueryType::SamplesPassed); |
| 537 | break; | 542 | break; |
| 538 | default: | 543 | default: |
| 539 | LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}", | 544 | LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}", |
| @@ -547,7 +552,7 @@ void Maxwell3D::ProcessSyncPoint() { | |||
| 547 | const u32 increment = regs.sync_info.increment.Value(); | 552 | const u32 increment = regs.sync_info.increment.Value(); |
| 548 | [[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value(); | 553 | [[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value(); |
| 549 | if (increment) { | 554 | if (increment) { |
| 550 | rasterizer.SignalSyncPoint(sync_point); | 555 | rasterizer->SignalSyncPoint(sync_point); |
| 551 | } | 556 | } |
| 552 | } | 557 | } |
| 553 | 558 | ||
| @@ -570,7 +575,7 @@ void Maxwell3D::DrawArrays() { | |||
| 570 | 575 | ||
| 571 | const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count}; | 576 | const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count}; |
| 572 | if (ShouldExecute()) { | 577 | if (ShouldExecute()) { |
| 573 | rasterizer.Draw(is_indexed, false); | 578 | rasterizer->Draw(is_indexed, false); |
| 574 | } | 579 | } |
| 575 | 580 | ||
| 576 | // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if | 581 | // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if |
| @@ -590,8 +595,8 @@ std::optional<u64> Maxwell3D::GetQueryResult() { | |||
| 590 | return 0; | 595 | return 0; |
| 591 | case Regs::QuerySelect::SamplesPassed: | 596 | case Regs::QuerySelect::SamplesPassed: |
| 592 | // Deferred. | 597 | // Deferred. |
| 593 | rasterizer.Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed, | 598 | rasterizer->Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed, |
| 594 | system.GPU().GetTicks()); | 599 | system.GPU().GetTicks()); |
| 595 | return {}; | 600 | return {}; |
| 596 | default: | 601 | default: |
| 597 | LOG_DEBUG(HW_GPU, "Unimplemented query select type {}", | 602 | LOG_DEBUG(HW_GPU, "Unimplemented query select type {}", |
| @@ -718,7 +723,7 @@ void Maxwell3D::ProcessClearBuffers() { | |||
| 718 | regs.clear_buffers.R == regs.clear_buffers.B && | 723 | regs.clear_buffers.R == regs.clear_buffers.B && |
| 719 | regs.clear_buffers.R == regs.clear_buffers.A); | 724 | regs.clear_buffers.R == regs.clear_buffers.A); |
| 720 | 725 | ||
| 721 | rasterizer.Clear(); | 726 | rasterizer->Clear(); |
| 722 | } | 727 | } |
| 723 | 728 | ||
| 724 | u32 Maxwell3D::AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const { | 729 | u32 Maxwell3D::AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const { |
| @@ -752,11 +757,11 @@ SamplerDescriptor Maxwell3D::AccessSampler(u32 handle) const { | |||
| 752 | } | 757 | } |
| 753 | 758 | ||
| 754 | VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() { | 759 | VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() { |
| 755 | return rasterizer.AccessGuestDriverProfile(); | 760 | return rasterizer->AccessGuestDriverProfile(); |
| 756 | } | 761 | } |
| 757 | 762 | ||
| 758 | const VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() const { | 763 | const VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() const { |
| 759 | return rasterizer.AccessGuestDriverProfile(); | 764 | return rasterizer->AccessGuestDriverProfile(); |
| 760 | } | 765 | } |
| 761 | 766 | ||
| 762 | } // namespace Tegra::Engines | 767 | } // namespace Tegra::Engines |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index c97eeb792..bc289c55d 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -51,9 +51,11 @@ namespace Tegra::Engines { | |||
| 51 | 51 | ||
| 52 | class Maxwell3D final : public ConstBufferEngineInterface, public EngineInterface { | 52 | class Maxwell3D final : public ConstBufferEngineInterface, public EngineInterface { |
| 53 | public: | 53 | public: |
| 54 | explicit Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | 54 | explicit Maxwell3D(Core::System& system, MemoryManager& memory_manager); |
| 55 | MemoryManager& memory_manager); | 55 | ~Maxwell3D(); |
| 56 | ~Maxwell3D() = default; | 56 | |
| 57 | /// Binds a rasterizer to this engine. | ||
| 58 | void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); | ||
| 57 | 59 | ||
| 58 | /// Register structure of the Maxwell3D engine. | 60 | /// Register structure of the Maxwell3D engine. |
| 59 | /// TODO(Subv): This structure will need to be made bigger as more registers are discovered. | 61 | /// TODO(Subv): This structure will need to be made bigger as more registers are discovered. |
| @@ -1418,12 +1420,12 @@ public: | |||
| 1418 | return execute_on; | 1420 | return execute_on; |
| 1419 | } | 1421 | } |
| 1420 | 1422 | ||
| 1421 | VideoCore::RasterizerInterface& GetRasterizer() { | 1423 | VideoCore::RasterizerInterface& Rasterizer() { |
| 1422 | return rasterizer; | 1424 | return *rasterizer; |
| 1423 | } | 1425 | } |
| 1424 | 1426 | ||
| 1425 | const VideoCore::RasterizerInterface& GetRasterizer() const { | 1427 | const VideoCore::RasterizerInterface& Rasterizer() const { |
| 1426 | return rasterizer; | 1428 | return *rasterizer; |
| 1427 | } | 1429 | } |
| 1428 | 1430 | ||
| 1429 | /// Notify a memory write has happened. | 1431 | /// Notify a memory write has happened. |
| @@ -1460,11 +1462,10 @@ private: | |||
| 1460 | void InitializeRegisterDefaults(); | 1462 | void InitializeRegisterDefaults(); |
| 1461 | 1463 | ||
| 1462 | Core::System& system; | 1464 | Core::System& system; |
| 1463 | |||
| 1464 | VideoCore::RasterizerInterface& rasterizer; | ||
| 1465 | |||
| 1466 | MemoryManager& memory_manager; | 1465 | MemoryManager& memory_manager; |
| 1467 | 1466 | ||
| 1467 | VideoCore::RasterizerInterface* rasterizer = nullptr; | ||
| 1468 | |||
| 1468 | /// Start offsets of each macro in macro_memory | 1469 | /// Start offsets of each macro in macro_memory |
| 1469 | std::array<u32, 0x80> macro_positions = {}; | 1470 | std::array<u32, 0x80> macro_positions = {}; |
| 1470 | 1471 | ||
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 512578c8b..acb6e6d46 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -27,21 +27,28 @@ namespace Tegra { | |||
| 27 | 27 | ||
| 28 | MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192)); | 28 | MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192)); |
| 29 | 29 | ||
| 30 | GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, bool is_async) | 30 | GPU::GPU(Core::System& system_, bool is_async_) |
| 31 | : system{system}, renderer{std::move(renderer_)}, is_async{is_async} { | 31 | : system{system_}, dma_pusher{std::make_unique<Tegra::DmaPusher>(system, *this)}, |
| 32 | auto& rasterizer{renderer->Rasterizer()}; | 32 | memory_manager{std::make_unique<Tegra::MemoryManager>(system)}, |
| 33 | memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer); | 33 | maxwell_3d{std::make_unique<Engines::Maxwell3D>(system, *memory_manager)}, |
| 34 | dma_pusher = std::make_unique<Tegra::DmaPusher>(system, *this); | 34 | fermi_2d{std::make_unique<Engines::Fermi2D>()}, |
| 35 | maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager); | 35 | kepler_compute{std::make_unique<Engines::KeplerCompute>(system, *memory_manager)}, |
| 36 | fermi_2d = std::make_unique<Engines::Fermi2D>(rasterizer); | 36 | maxwell_dma{std::make_unique<Engines::MaxwellDMA>(system, *memory_manager)}, |
| 37 | kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager); | 37 | kepler_memory{std::make_unique<Engines::KeplerMemory>(system, *memory_manager)}, |
| 38 | maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager); | 38 | shader_notify{std::make_unique<VideoCore::ShaderNotify>()}, is_async{is_async_} {} |
| 39 | kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager); | ||
| 40 | shader_notify = std::make_unique<VideoCore::ShaderNotify>(); | ||
| 41 | } | ||
| 42 | 39 | ||
| 43 | GPU::~GPU() = default; | 40 | GPU::~GPU() = default; |
| 44 | 41 | ||
| 42 | void GPU::BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) { | ||
| 43 | renderer = std::move(renderer_); | ||
| 44 | |||
| 45 | VideoCore::RasterizerInterface& rasterizer = renderer->Rasterizer(); | ||
| 46 | memory_manager->BindRasterizer(rasterizer); | ||
| 47 | maxwell_3d->BindRasterizer(rasterizer); | ||
| 48 | fermi_2d->BindRasterizer(rasterizer); | ||
| 49 | kepler_compute->BindRasterizer(rasterizer); | ||
| 50 | } | ||
| 51 | |||
| 45 | Engines::Maxwell3D& GPU::Maxwell3D() { | 52 | Engines::Maxwell3D& GPU::Maxwell3D() { |
| 46 | return *maxwell_3d; | 53 | return *maxwell_3d; |
| 47 | } | 54 | } |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index ebfc7b0c7..c7d11deb2 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -142,11 +142,6 @@ class MemoryManager; | |||
| 142 | 142 | ||
| 143 | class GPU { | 143 | class GPU { |
| 144 | public: | 144 | public: |
| 145 | explicit GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, | ||
| 146 | bool is_async); | ||
| 147 | |||
| 148 | virtual ~GPU(); | ||
| 149 | |||
| 150 | struct MethodCall { | 145 | struct MethodCall { |
| 151 | u32 method{}; | 146 | u32 method{}; |
| 152 | u32 argument{}; | 147 | u32 argument{}; |
| @@ -162,6 +157,12 @@ public: | |||
| 162 | method_count(method_count) {} | 157 | method_count(method_count) {} |
| 163 | }; | 158 | }; |
| 164 | 159 | ||
| 160 | explicit GPU(Core::System& system, bool is_async); | ||
| 161 | virtual ~GPU(); | ||
| 162 | |||
| 163 | /// Binds a renderer to the GPU. | ||
| 164 | void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer); | ||
| 165 | |||
| 165 | /// Calls a GPU method. | 166 | /// Calls a GPU method. |
| 166 | void CallMethod(const MethodCall& method_call); | 167 | void CallMethod(const MethodCall& method_call); |
| 167 | 168 | ||
| @@ -345,8 +346,8 @@ private: | |||
| 345 | bool ExecuteMethodOnEngine(u32 method); | 346 | bool ExecuteMethodOnEngine(u32 method); |
| 346 | 347 | ||
| 347 | protected: | 348 | protected: |
| 348 | std::unique_ptr<Tegra::DmaPusher> dma_pusher; | ||
| 349 | Core::System& system; | 349 | Core::System& system; |
| 350 | std::unique_ptr<Tegra::DmaPusher> dma_pusher; | ||
| 350 | std::unique_ptr<VideoCore::RendererBase> renderer; | 351 | std::unique_ptr<VideoCore::RendererBase> renderer; |
| 351 | 352 | ||
| 352 | private: | 353 | private: |
diff --git a/src/video_core/gpu_asynch.cpp b/src/video_core/gpu_asynch.cpp index 7b855f63e..70a3d5738 100644 --- a/src/video_core/gpu_asynch.cpp +++ b/src/video_core/gpu_asynch.cpp | |||
| @@ -10,16 +10,14 @@ | |||
| 10 | 10 | ||
| 11 | namespace VideoCommon { | 11 | namespace VideoCommon { |
| 12 | 12 | ||
| 13 | GPUAsynch::GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, | 13 | GPUAsynch::GPUAsynch(Core::System& system) : GPU{system, true}, gpu_thread{system} {} |
| 14 | std::unique_ptr<Core::Frontend::GraphicsContext>&& context) | ||
| 15 | : GPU(system, std::move(renderer_), true), gpu_thread{system}, | ||
| 16 | cpu_context(renderer->GetRenderWindow().CreateSharedContext()), | ||
| 17 | gpu_context(std::move(context)) {} | ||
| 18 | 14 | ||
| 19 | GPUAsynch::~GPUAsynch() = default; | 15 | GPUAsynch::~GPUAsynch() = default; |
| 20 | 16 | ||
| 21 | void GPUAsynch::Start() { | 17 | void GPUAsynch::Start() { |
| 22 | gpu_thread.StartThread(*renderer, *gpu_context, *dma_pusher); | 18 | gpu_thread.StartThread(*renderer, renderer->Context(), *dma_pusher); |
| 19 | cpu_context = renderer->GetRenderWindow().CreateSharedContext(); | ||
| 20 | cpu_context->MakeCurrent(); | ||
| 23 | } | 21 | } |
| 24 | 22 | ||
| 25 | void GPUAsynch::ObtainContext() { | 23 | void GPUAsynch::ObtainContext() { |
diff --git a/src/video_core/gpu_asynch.h b/src/video_core/gpu_asynch.h index 15e9f1d38..f89c855a5 100644 --- a/src/video_core/gpu_asynch.h +++ b/src/video_core/gpu_asynch.h | |||
| @@ -20,8 +20,7 @@ namespace VideoCommon { | |||
| 20 | /// Implementation of GPU interface that runs the GPU asynchronously | 20 | /// Implementation of GPU interface that runs the GPU asynchronously |
| 21 | class GPUAsynch final : public Tegra::GPU { | 21 | class GPUAsynch final : public Tegra::GPU { |
| 22 | public: | 22 | public: |
| 23 | explicit GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, | 23 | explicit GPUAsynch(Core::System& system); |
| 24 | std::unique_ptr<Core::Frontend::GraphicsContext>&& context); | ||
| 25 | ~GPUAsynch() override; | 24 | ~GPUAsynch() override; |
| 26 | 25 | ||
| 27 | void Start() override; | 26 | void Start() override; |
| @@ -42,7 +41,6 @@ protected: | |||
| 42 | private: | 41 | private: |
| 43 | GPUThread::ThreadManager gpu_thread; | 42 | GPUThread::ThreadManager gpu_thread; |
| 44 | std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context; | 43 | std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context; |
| 45 | std::unique_ptr<Core::Frontend::GraphicsContext> gpu_context; | ||
| 46 | }; | 44 | }; |
| 47 | 45 | ||
| 48 | } // namespace VideoCommon | 46 | } // namespace VideoCommon |
diff --git a/src/video_core/gpu_synch.cpp b/src/video_core/gpu_synch.cpp index aaeb9811d..1ca47ddef 100644 --- a/src/video_core/gpu_synch.cpp +++ b/src/video_core/gpu_synch.cpp | |||
| @@ -7,20 +7,18 @@ | |||
| 7 | 7 | ||
| 8 | namespace VideoCommon { | 8 | namespace VideoCommon { |
| 9 | 9 | ||
| 10 | GPUSynch::GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, | 10 | GPUSynch::GPUSynch(Core::System& system) : GPU{system, false} {} |
| 11 | std::unique_ptr<Core::Frontend::GraphicsContext>&& context) | ||
| 12 | : GPU(system, std::move(renderer), false), context{std::move(context)} {} | ||
| 13 | 11 | ||
| 14 | GPUSynch::~GPUSynch() = default; | 12 | GPUSynch::~GPUSynch() = default; |
| 15 | 13 | ||
| 16 | void GPUSynch::Start() {} | 14 | void GPUSynch::Start() {} |
| 17 | 15 | ||
| 18 | void GPUSynch::ObtainContext() { | 16 | void GPUSynch::ObtainContext() { |
| 19 | context->MakeCurrent(); | 17 | renderer->Context().MakeCurrent(); |
| 20 | } | 18 | } |
| 21 | 19 | ||
| 22 | void GPUSynch::ReleaseContext() { | 20 | void GPUSynch::ReleaseContext() { |
| 23 | context->DoneCurrent(); | 21 | renderer->Context().DoneCurrent(); |
| 24 | } | 22 | } |
| 25 | 23 | ||
| 26 | void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { | 24 | void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { |
diff --git a/src/video_core/gpu_synch.h b/src/video_core/gpu_synch.h index 762c20aa5..297258cb1 100644 --- a/src/video_core/gpu_synch.h +++ b/src/video_core/gpu_synch.h | |||
| @@ -19,8 +19,7 @@ namespace VideoCommon { | |||
| 19 | /// Implementation of GPU interface that runs the GPU synchronously | 19 | /// Implementation of GPU interface that runs the GPU synchronously |
| 20 | class GPUSynch final : public Tegra::GPU { | 20 | class GPUSynch final : public Tegra::GPU { |
| 21 | public: | 21 | public: |
| 22 | explicit GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, | 22 | explicit GPUSynch(Core::System& system); |
| 23 | std::unique_ptr<Core::Frontend::GraphicsContext>&& context); | ||
| 24 | ~GPUSynch() override; | 23 | ~GPUSynch() override; |
| 25 | 24 | ||
| 26 | void Start() override; | 25 | void Start() override; |
| @@ -36,9 +35,6 @@ public: | |||
| 36 | protected: | 35 | protected: |
| 37 | void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id, | 36 | void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id, |
| 38 | [[maybe_unused]] u32 value) const override {} | 37 | [[maybe_unused]] u32 value) const override {} |
| 39 | |||
| 40 | private: | ||
| 41 | std::unique_ptr<Core::Frontend::GraphicsContext> context; | ||
| 42 | }; | 38 | }; |
| 43 | 39 | ||
| 44 | } // namespace VideoCommon | 40 | } // namespace VideoCommon |
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt new file mode 100644 index 000000000..aa62363a7 --- /dev/null +++ b/src/video_core/host_shaders/CMakeLists.txt | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | set(SHADER_FILES | ||
| 2 | opengl_present.frag | ||
| 3 | opengl_present.vert | ||
| 4 | ) | ||
| 5 | |||
| 6 | set(SHADER_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/include) | ||
| 7 | set(HOST_SHADERS_INCLUDE ${SHADER_INCLUDE} PARENT_SCOPE) | ||
| 8 | |||
| 9 | set(SHADER_DIR ${SHADER_INCLUDE}/video_core/host_shaders) | ||
| 10 | add_custom_command( | ||
| 11 | OUTPUT | ||
| 12 | ${SHADER_DIR} | ||
| 13 | COMMAND | ||
| 14 | ${CMAKE_COMMAND} -E make_directory ${SHADER_DIR} | ||
| 15 | ) | ||
| 16 | |||
| 17 | set(INPUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/source_shader.h.in) | ||
| 18 | set(HEADER_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/StringShaderHeader.cmake) | ||
| 19 | |||
| 20 | foreach(FILENAME IN ITEMS ${SHADER_FILES}) | ||
| 21 | string(REPLACE "." "_" SHADER_NAME ${FILENAME}) | ||
| 22 | set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}) | ||
| 23 | set(HEADER_FILE ${SHADER_DIR}/${SHADER_NAME}.h) | ||
| 24 | add_custom_command( | ||
| 25 | OUTPUT | ||
| 26 | ${HEADER_FILE} | ||
| 27 | COMMAND | ||
| 28 | ${CMAKE_COMMAND} -P ${HEADER_GENERATOR} ${SOURCE_FILE} ${HEADER_FILE} ${INPUT_FILE} | ||
| 29 | MAIN_DEPENDENCY | ||
| 30 | ${SOURCE_FILE} | ||
| 31 | DEPENDS | ||
| 32 | ${HEADER_GENERATOR} | ||
| 33 | ${INPUT_FILE} | ||
| 34 | ) | ||
| 35 | set(SHADER_HEADERS ${SHADER_HEADERS} ${HEADER_FILE}) | ||
| 36 | endforeach() | ||
| 37 | |||
| 38 | add_custom_target(host_shaders | ||
| 39 | DEPENDS | ||
| 40 | ${SHADER_HEADERS} | ||
| 41 | SOURCES | ||
| 42 | ${SHADER_FILES} | ||
| 43 | ) | ||
diff --git a/src/video_core/host_shaders/StringShaderHeader.cmake b/src/video_core/host_shaders/StringShaderHeader.cmake new file mode 100644 index 000000000..368bce0ed --- /dev/null +++ b/src/video_core/host_shaders/StringShaderHeader.cmake | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | set(SOURCE_FILE ${CMAKE_ARGV3}) | ||
| 2 | set(HEADER_FILE ${CMAKE_ARGV4}) | ||
| 3 | set(INPUT_FILE ${CMAKE_ARGV5}) | ||
| 4 | |||
| 5 | get_filename_component(CONTENTS_NAME ${SOURCE_FILE} NAME) | ||
| 6 | string(REPLACE "." "_" CONTENTS_NAME ${CONTENTS_NAME}) | ||
| 7 | string(TOUPPER ${CONTENTS_NAME} CONTENTS_NAME) | ||
| 8 | |||
| 9 | file(READ ${SOURCE_FILE} CONTENTS) | ||
| 10 | |||
| 11 | configure_file(${INPUT_FILE} ${HEADER_FILE} @ONLY) | ||
diff --git a/src/video_core/host_shaders/opengl_present.frag b/src/video_core/host_shaders/opengl_present.frag new file mode 100644 index 000000000..8a4cb024b --- /dev/null +++ b/src/video_core/host_shaders/opengl_present.frag | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #version 430 core | ||
| 2 | |||
| 3 | layout (location = 0) in vec2 frag_tex_coord; | ||
| 4 | layout (location = 0) out vec4 color; | ||
| 5 | |||
| 6 | layout (binding = 0) uniform sampler2D color_texture; | ||
| 7 | |||
| 8 | void main() { | ||
| 9 | color = vec4(texture(color_texture, frag_tex_coord).rgb, 1.0f); | ||
| 10 | } | ||
diff --git a/src/video_core/host_shaders/opengl_present.vert b/src/video_core/host_shaders/opengl_present.vert new file mode 100644 index 000000000..2235d31a4 --- /dev/null +++ b/src/video_core/host_shaders/opengl_present.vert | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | #version 430 core | ||
| 2 | |||
| 3 | out gl_PerVertex { | ||
| 4 | vec4 gl_Position; | ||
| 5 | }; | ||
| 6 | |||
| 7 | layout (location = 0) in vec2 vert_position; | ||
| 8 | layout (location = 1) in vec2 vert_tex_coord; | ||
| 9 | layout (location = 0) out vec2 frag_tex_coord; | ||
| 10 | |||
| 11 | // This is a truncated 3x3 matrix for 2D transformations: | ||
| 12 | // The upper-left 2x2 submatrix performs scaling/rotation/mirroring. | ||
| 13 | // The third column performs translation. | ||
| 14 | // The third row could be used for projection, which we don't need in 2D. It hence is assumed to | ||
| 15 | // implicitly be [0, 0, 1] | ||
| 16 | layout (location = 0) uniform mat3x2 modelview_matrix; | ||
| 17 | |||
| 18 | void main() { | ||
| 19 | // Multiply input position by the rotscale part of the matrix and then manually translate by | ||
| 20 | // the last column. This is equivalent to using a full 3x3 matrix and expanding the vector | ||
| 21 | // to `vec3(vert_position.xy, 1.0)` | ||
| 22 | gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0); | ||
| 23 | frag_tex_coord = vert_tex_coord; | ||
| 24 | } | ||
diff --git a/src/video_core/host_shaders/source_shader.h.in b/src/video_core/host_shaders/source_shader.h.in new file mode 100644 index 000000000..ccdb0d2a9 --- /dev/null +++ b/src/video_core/host_shaders/source_shader.h.in | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <string_view> | ||
| 4 | |||
| 5 | namespace HostShaders { | ||
| 6 | |||
| 7 | constexpr std::string_view @CONTENTS_NAME@ = R"(@CONTENTS@)"; | ||
| 8 | |||
| 9 | } // namespace HostShaders | ||
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index 0c9ff59a4..df00b57df 100644 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp | |||
| @@ -24,7 +24,7 @@ void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& | |||
| 24 | maxwell3d.regs.index_array.first = parameters[4]; | 24 | maxwell3d.regs.index_array.first = parameters[4]; |
| 25 | 25 | ||
| 26 | if (maxwell3d.ShouldExecute()) { | 26 | if (maxwell3d.ShouldExecute()) { |
| 27 | maxwell3d.GetRasterizer().Draw(true, true); | 27 | maxwell3d.Rasterizer().Draw(true, true); |
| 28 | } | 28 | } |
| 29 | maxwell3d.regs.index_array.count = 0; | 29 | maxwell3d.regs.index_array.count = 0; |
| 30 | maxwell3d.mme_draw.instance_count = 0; | 30 | maxwell3d.mme_draw.instance_count = 0; |
| @@ -42,7 +42,7 @@ void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& | |||
| 42 | maxwell3d.mme_draw.instance_count = count; | 42 | maxwell3d.mme_draw.instance_count = count; |
| 43 | 43 | ||
| 44 | if (maxwell3d.ShouldExecute()) { | 44 | if (maxwell3d.ShouldExecute()) { |
| 45 | maxwell3d.GetRasterizer().Draw(false, true); | 45 | maxwell3d.Rasterizer().Draw(false, true); |
| 46 | } | 46 | } |
| 47 | maxwell3d.regs.vertex_buffer.count = 0; | 47 | maxwell3d.regs.vertex_buffer.count = 0; |
| 48 | maxwell3d.mme_draw.instance_count = 0; | 48 | maxwell3d.mme_draw.instance_count = 0; |
| @@ -65,7 +65,7 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& | |||
| 65 | maxwell3d.regs.draw.topology.Assign( | 65 | maxwell3d.regs.draw.topology.Assign( |
| 66 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0])); | 66 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0])); |
| 67 | if (maxwell3d.ShouldExecute()) { | 67 | if (maxwell3d.ShouldExecute()) { |
| 68 | maxwell3d.GetRasterizer().Draw(true, true); | 68 | maxwell3d.Rasterizer().Draw(true, true); |
| 69 | } | 69 | } |
| 70 | maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base? | 70 | maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base? |
| 71 | maxwell3d.regs.index_array.count = 0; | 71 | maxwell3d.regs.index_array.count = 0; |
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 844164645..16b2aaa27 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp | |||
| @@ -14,11 +14,15 @@ | |||
| 14 | 14 | ||
| 15 | namespace Tegra { | 15 | namespace Tegra { |
| 16 | 16 | ||
| 17 | MemoryManager::MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer) | 17 | MemoryManager::MemoryManager(Core::System& system_) |
| 18 | : system{system}, rasterizer{rasterizer}, page_table(page_table_size) {} | 18 | : system{system_}, page_table(page_table_size) {} |
| 19 | 19 | ||
| 20 | MemoryManager::~MemoryManager() = default; | 20 | MemoryManager::~MemoryManager() = default; |
| 21 | 21 | ||
| 22 | void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { | ||
| 23 | rasterizer = &rasterizer_; | ||
| 24 | } | ||
| 25 | |||
| 22 | GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) { | 26 | GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) { |
| 23 | u64 remaining_size{size}; | 27 | u64 remaining_size{size}; |
| 24 | for (u64 offset{}; offset < size; offset += page_size) { | 28 | for (u64 offset{}; offset < size; offset += page_size) { |
| @@ -217,7 +221,7 @@ void MemoryManager::ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, std::siz | |||
| 217 | 221 | ||
| 218 | // Flush must happen on the rasterizer interface, such that memory is always synchronous | 222 | // Flush must happen on the rasterizer interface, such that memory is always synchronous |
| 219 | // when it is read (even when in asynchronous GPU mode). Fixes Dead Cells title menu. | 223 | // when it is read (even when in asynchronous GPU mode). Fixes Dead Cells title menu. |
| 220 | rasterizer.FlushRegion(src_addr, copy_amount); | 224 | rasterizer->FlushRegion(src_addr, copy_amount); |
| 221 | system.Memory().ReadBlockUnsafe(src_addr, dest_buffer, copy_amount); | 225 | system.Memory().ReadBlockUnsafe(src_addr, dest_buffer, copy_amount); |
| 222 | } | 226 | } |
| 223 | 227 | ||
| @@ -266,7 +270,7 @@ void MemoryManager::WriteBlock(GPUVAddr gpu_dest_addr, const void* src_buffer, s | |||
| 266 | 270 | ||
| 267 | // Invalidate must happen on the rasterizer interface, such that memory is always | 271 | // Invalidate must happen on the rasterizer interface, such that memory is always |
| 268 | // synchronous when it is written (even when in asynchronous GPU mode). | 272 | // synchronous when it is written (even when in asynchronous GPU mode). |
| 269 | rasterizer.InvalidateRegion(dest_addr, copy_amount); | 273 | rasterizer->InvalidateRegion(dest_addr, copy_amount); |
| 270 | system.Memory().WriteBlockUnsafe(dest_addr, src_buffer, copy_amount); | 274 | system.Memory().WriteBlockUnsafe(dest_addr, src_buffer, copy_amount); |
| 271 | } | 275 | } |
| 272 | 276 | ||
| @@ -312,10 +316,10 @@ void MemoryManager::CopyBlockUnsafe(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_add | |||
| 312 | WriteBlockUnsafe(gpu_dest_addr, tmp_buffer.data(), size); | 316 | WriteBlockUnsafe(gpu_dest_addr, tmp_buffer.data(), size); |
| 313 | } | 317 | } |
| 314 | 318 | ||
| 315 | bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) { | 319 | bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const { |
| 316 | const auto cpu_addr{GpuToCpuAddress(gpu_addr)}; | 320 | const auto cpu_addr{GpuToCpuAddress(gpu_addr)}; |
| 317 | if (!cpu_addr) { | 321 | if (!cpu_addr) { |
| 318 | return {}; | 322 | return false; |
| 319 | } | 323 | } |
| 320 | const std::size_t page{(*cpu_addr & Core::Memory::PAGE_MASK) + size}; | 324 | const std::size_t page{(*cpu_addr & Core::Memory::PAGE_MASK) + size}; |
| 321 | return page <= Core::Memory::PAGE_SIZE; | 325 | return page <= Core::Memory::PAGE_SIZE; |
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index 681bd9588..53c8d122a 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h | |||
| @@ -31,19 +31,19 @@ public: | |||
| 31 | constexpr PageEntry(State state) : state{state} {} | 31 | constexpr PageEntry(State state) : state{state} {} |
| 32 | constexpr PageEntry(VAddr addr) : state{static_cast<State>(addr >> ShiftBits)} {} | 32 | constexpr PageEntry(VAddr addr) : state{static_cast<State>(addr >> ShiftBits)} {} |
| 33 | 33 | ||
| 34 | constexpr bool IsUnmapped() const { | 34 | [[nodiscard]] constexpr bool IsUnmapped() const { |
| 35 | return state == State::Unmapped; | 35 | return state == State::Unmapped; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | constexpr bool IsAllocated() const { | 38 | [[nodiscard]] constexpr bool IsAllocated() const { |
| 39 | return state == State::Allocated; | 39 | return state == State::Allocated; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | constexpr bool IsValid() const { | 42 | [[nodiscard]] constexpr bool IsValid() const { |
| 43 | return !IsUnmapped() && !IsAllocated(); | 43 | return !IsUnmapped() && !IsAllocated(); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | constexpr VAddr ToAddress() const { | 46 | [[nodiscard]] constexpr VAddr ToAddress() const { |
| 47 | if (!IsValid()) { | 47 | if (!IsValid()) { |
| 48 | return {}; | 48 | return {}; |
| 49 | } | 49 | } |
| @@ -51,7 +51,7 @@ public: | |||
| 51 | return static_cast<VAddr>(state) << ShiftBits; | 51 | return static_cast<VAddr>(state) << ShiftBits; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | constexpr PageEntry operator+(u64 offset) { | 54 | [[nodiscard]] constexpr PageEntry operator+(u64 offset) const { |
| 55 | // If this is a reserved value, offsets do not apply | 55 | // If this is a reserved value, offsets do not apply |
| 56 | if (!IsValid()) { | 56 | if (!IsValid()) { |
| 57 | return *this; | 57 | return *this; |
| @@ -68,19 +68,22 @@ static_assert(sizeof(PageEntry) == 4, "PageEntry is too large"); | |||
| 68 | 68 | ||
| 69 | class MemoryManager final { | 69 | class MemoryManager final { |
| 70 | public: | 70 | public: |
| 71 | explicit MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer); | 71 | explicit MemoryManager(Core::System& system); |
| 72 | ~MemoryManager(); | 72 | ~MemoryManager(); |
| 73 | 73 | ||
| 74 | std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const; | 74 | /// Binds a renderer to the memory manager. |
| 75 | void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); | ||
| 76 | |||
| 77 | [[nodiscard]] std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const; | ||
| 75 | 78 | ||
| 76 | template <typename T> | 79 | template <typename T> |
| 77 | T Read(GPUVAddr addr) const; | 80 | [[nodiscard]] T Read(GPUVAddr addr) const; |
| 78 | 81 | ||
| 79 | template <typename T> | 82 | template <typename T> |
| 80 | void Write(GPUVAddr addr, T data); | 83 | void Write(GPUVAddr addr, T data); |
| 81 | 84 | ||
| 82 | u8* GetPointer(GPUVAddr addr); | 85 | [[nodiscard]] u8* GetPointer(GPUVAddr addr); |
| 83 | const u8* GetPointer(GPUVAddr addr) const; | 86 | [[nodiscard]] const u8* GetPointer(GPUVAddr addr) const; |
| 84 | 87 | ||
| 85 | /** | 88 | /** |
| 86 | * ReadBlock and WriteBlock are full read and write operations over virtual | 89 | * ReadBlock and WriteBlock are full read and write operations over virtual |
| @@ -109,24 +112,24 @@ public: | |||
| 109 | /** | 112 | /** |
| 110 | * IsGranularRange checks if a gpu region can be simply read with a pointer. | 113 | * IsGranularRange checks if a gpu region can be simply read with a pointer. |
| 111 | */ | 114 | */ |
| 112 | bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size); | 115 | [[nodiscard]] bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const; |
| 113 | 116 | ||
| 114 | GPUVAddr Map(VAddr cpu_addr, GPUVAddr gpu_addr, std::size_t size); | 117 | [[nodiscard]] GPUVAddr Map(VAddr cpu_addr, GPUVAddr gpu_addr, std::size_t size); |
| 115 | GPUVAddr MapAllocate(VAddr cpu_addr, std::size_t size, std::size_t align); | 118 | [[nodiscard]] GPUVAddr MapAllocate(VAddr cpu_addr, std::size_t size, std::size_t align); |
| 116 | std::optional<GPUVAddr> AllocateFixed(GPUVAddr gpu_addr, std::size_t size); | 119 | [[nodiscard]] std::optional<GPUVAddr> AllocateFixed(GPUVAddr gpu_addr, std::size_t size); |
| 117 | GPUVAddr Allocate(std::size_t size, std::size_t align); | 120 | [[nodiscard]] GPUVAddr Allocate(std::size_t size, std::size_t align); |
| 118 | void Unmap(GPUVAddr gpu_addr, std::size_t size); | 121 | void Unmap(GPUVAddr gpu_addr, std::size_t size); |
| 119 | 122 | ||
| 120 | private: | 123 | private: |
| 121 | PageEntry GetPageEntry(GPUVAddr gpu_addr) const; | 124 | [[nodiscard]] PageEntry GetPageEntry(GPUVAddr gpu_addr) const; |
| 122 | void SetPageEntry(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size = page_size); | 125 | void SetPageEntry(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size = page_size); |
| 123 | GPUVAddr UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size); | 126 | GPUVAddr UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size); |
| 124 | std::optional<GPUVAddr> FindFreeRange(std::size_t size, std::size_t align) const; | 127 | [[nodiscard]] std::optional<GPUVAddr> FindFreeRange(std::size_t size, std::size_t align) const; |
| 125 | 128 | ||
| 126 | void TryLockPage(PageEntry page_entry, std::size_t size); | 129 | void TryLockPage(PageEntry page_entry, std::size_t size); |
| 127 | void TryUnlockPage(PageEntry page_entry, std::size_t size); | 130 | void TryUnlockPage(PageEntry page_entry, std::size_t size); |
| 128 | 131 | ||
| 129 | static constexpr std::size_t PageEntryIndex(GPUVAddr gpu_addr) { | 132 | [[nodiscard]] static constexpr std::size_t PageEntryIndex(GPUVAddr gpu_addr) { |
| 130 | return (gpu_addr >> page_bits) & page_table_mask; | 133 | return (gpu_addr >> page_bits) & page_table_mask; |
| 131 | } | 134 | } |
| 132 | 135 | ||
| @@ -141,7 +144,7 @@ private: | |||
| 141 | 144 | ||
| 142 | Core::System& system; | 145 | Core::System& system; |
| 143 | 146 | ||
| 144 | VideoCore::RasterizerInterface& rasterizer; | 147 | VideoCore::RasterizerInterface* rasterizer = nullptr; |
| 145 | 148 | ||
| 146 | std::vector<PageEntry> page_table; | 149 | std::vector<PageEntry> page_table; |
| 147 | }; | 150 | }; |
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp index dfb06e87e..a93a1732c 100644 --- a/src/video_core/renderer_base.cpp +++ b/src/video_core/renderer_base.cpp | |||
| @@ -9,7 +9,9 @@ | |||
| 9 | 9 | ||
| 10 | namespace VideoCore { | 10 | namespace VideoCore { |
| 11 | 11 | ||
| 12 | RendererBase::RendererBase(Core::Frontend::EmuWindow& window) : render_window{window} { | 12 | RendererBase::RendererBase(Core::Frontend::EmuWindow& window_, |
| 13 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) | ||
| 14 | : render_window{window_}, context{std::move(context_)} { | ||
| 13 | RefreshBaseSettings(); | 15 | RefreshBaseSettings(); |
| 14 | } | 16 | } |
| 15 | 17 | ||
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 1d85219b6..649074acd 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h | |||
| @@ -15,7 +15,8 @@ | |||
| 15 | 15 | ||
| 16 | namespace Core::Frontend { | 16 | namespace Core::Frontend { |
| 17 | class EmuWindow; | 17 | class EmuWindow; |
| 18 | } | 18 | class GraphicsContext; |
| 19 | } // namespace Core::Frontend | ||
| 19 | 20 | ||
| 20 | namespace VideoCore { | 21 | namespace VideoCore { |
| 21 | 22 | ||
| @@ -25,14 +26,15 @@ struct RendererSettings { | |||
| 25 | 26 | ||
| 26 | // Screenshot | 27 | // Screenshot |
| 27 | std::atomic<bool> screenshot_requested{false}; | 28 | std::atomic<bool> screenshot_requested{false}; |
| 28 | void* screenshot_bits; | 29 | void* screenshot_bits{}; |
| 29 | std::function<void()> screenshot_complete_callback; | 30 | std::function<void()> screenshot_complete_callback; |
| 30 | Layout::FramebufferLayout screenshot_framebuffer_layout; | 31 | Layout::FramebufferLayout screenshot_framebuffer_layout; |
| 31 | }; | 32 | }; |
| 32 | 33 | ||
| 33 | class RendererBase : NonCopyable { | 34 | class RendererBase : NonCopyable { |
| 34 | public: | 35 | public: |
| 35 | explicit RendererBase(Core::Frontend::EmuWindow& window); | 36 | explicit RendererBase(Core::Frontend::EmuWindow& window, |
| 37 | std::unique_ptr<Core::Frontend::GraphicsContext> context); | ||
| 36 | virtual ~RendererBase(); | 38 | virtual ~RendererBase(); |
| 37 | 39 | ||
| 38 | /// Initialize the renderer | 40 | /// Initialize the renderer |
| @@ -68,6 +70,14 @@ public: | |||
| 68 | return *rasterizer; | 70 | return *rasterizer; |
| 69 | } | 71 | } |
| 70 | 72 | ||
| 73 | Core::Frontend::GraphicsContext& Context() { | ||
| 74 | return *context; | ||
| 75 | } | ||
| 76 | |||
| 77 | const Core::Frontend::GraphicsContext& Context() const { | ||
| 78 | return *context; | ||
| 79 | } | ||
| 80 | |||
| 71 | Core::Frontend::EmuWindow& GetRenderWindow() { | 81 | Core::Frontend::EmuWindow& GetRenderWindow() { |
| 72 | return render_window; | 82 | return render_window; |
| 73 | } | 83 | } |
| @@ -94,6 +104,7 @@ public: | |||
| 94 | protected: | 104 | protected: |
| 95 | Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle. | 105 | Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle. |
| 96 | std::unique_ptr<RasterizerInterface> rasterizer; | 106 | std::unique_ptr<RasterizerInterface> rasterizer; |
| 107 | std::unique_ptr<Core::Frontend::GraphicsContext> context; | ||
| 97 | f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer | 108 | f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer |
| 98 | int m_current_frame = 0; ///< Current frame, should be set by the renderer | 109 | int m_current_frame = 0; ///< Current frame, should be set by the renderer |
| 99 | 110 | ||
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp index a787e27d2..0ebcec427 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <string_view> | ||
| 5 | #include <utility> | 6 | #include <utility> |
| 6 | #include <glad/glad.h> | 7 | #include <glad/glad.h> |
| 7 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| @@ -82,11 +83,13 @@ void OGLSampler::Release() { | |||
| 82 | handle = 0; | 83 | handle = 0; |
| 83 | } | 84 | } |
| 84 | 85 | ||
| 85 | void OGLShader::Create(const char* source, GLenum type) { | 86 | void OGLShader::Create(std::string_view source, GLenum type) { |
| 86 | if (handle != 0) | 87 | if (handle != 0) { |
| 87 | return; | 88 | return; |
| 88 | if (source == nullptr) | 89 | } |
| 90 | if (source.empty()) { | ||
| 89 | return; | 91 | return; |
| 92 | } | ||
| 90 | 93 | ||
| 91 | MICROPROFILE_SCOPE(OpenGL_ResourceCreation); | 94 | MICROPROFILE_SCOPE(OpenGL_ResourceCreation); |
| 92 | handle = GLShader::LoadShader(source, type); | 95 | handle = GLShader::LoadShader(source, type); |
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index b05cb641c..f48398669 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <string_view> | ||
| 7 | #include <utility> | 8 | #include <utility> |
| 8 | #include <glad/glad.h> | 9 | #include <glad/glad.h> |
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| @@ -127,7 +128,7 @@ public: | |||
| 127 | return *this; | 128 | return *this; |
| 128 | } | 129 | } |
| 129 | 130 | ||
| 130 | void Create(const char* source, GLenum type); | 131 | void Create(std::string_view source, GLenum type); |
| 131 | 132 | ||
| 132 | void Release(); | 133 | void Release(); |
| 133 | 134 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index eb49a36bf..a07d56ef0 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include "video_core/memory_manager.h" | 22 | #include "video_core/memory_manager.h" |
| 23 | #include "video_core/renderer_opengl/gl_arb_decompiler.h" | 23 | #include "video_core/renderer_opengl/gl_arb_decompiler.h" |
| 24 | #include "video_core/renderer_opengl/gl_rasterizer.h" | 24 | #include "video_core/renderer_opengl/gl_rasterizer.h" |
| 25 | #include "video_core/renderer_opengl/gl_resource_manager.h" | ||
| 25 | #include "video_core/renderer_opengl/gl_shader_cache.h" | 26 | #include "video_core/renderer_opengl/gl_shader_cache.h" |
| 26 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" | 27 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" |
| 27 | #include "video_core/renderer_opengl/gl_shader_disk_cache.h" | 28 | #include "video_core/renderer_opengl/gl_shader_disk_cache.h" |
diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp index 9e74eda0d..4bf0d6090 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.cpp +++ b/src/video_core/renderer_opengl/gl_shader_util.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <string_view> | ||
| 5 | #include <vector> | 6 | #include <vector> |
| 6 | #include <glad/glad.h> | 7 | #include <glad/glad.h> |
| 7 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| @@ -11,7 +12,8 @@ | |||
| 11 | namespace OpenGL::GLShader { | 12 | namespace OpenGL::GLShader { |
| 12 | 13 | ||
| 13 | namespace { | 14 | namespace { |
| 14 | const char* GetStageDebugName(GLenum type) { | 15 | |
| 16 | std::string_view StageDebugName(GLenum type) { | ||
| 15 | switch (type) { | 17 | switch (type) { |
| 16 | case GL_VERTEX_SHADER: | 18 | case GL_VERTEX_SHADER: |
| 17 | return "vertex"; | 19 | return "vertex"; |
| @@ -25,12 +27,17 @@ const char* GetStageDebugName(GLenum type) { | |||
| 25 | UNIMPLEMENTED(); | 27 | UNIMPLEMENTED(); |
| 26 | return "unknown"; | 28 | return "unknown"; |
| 27 | } | 29 | } |
| 30 | |||
| 28 | } // Anonymous namespace | 31 | } // Anonymous namespace |
| 29 | 32 | ||
| 30 | GLuint LoadShader(const char* source, GLenum type) { | 33 | GLuint LoadShader(std::string_view source, GLenum type) { |
| 31 | const char* debug_type = GetStageDebugName(type); | 34 | const std::string_view debug_type = StageDebugName(type); |
| 32 | const GLuint shader_id = glCreateShader(type); | 35 | const GLuint shader_id = glCreateShader(type); |
| 33 | glShaderSource(shader_id, 1, &source, nullptr); | 36 | |
| 37 | const GLchar* source_string = source.data(); | ||
| 38 | const GLint source_length = static_cast<GLint>(source.size()); | ||
| 39 | |||
| 40 | glShaderSource(shader_id, 1, &source_string, &source_length); | ||
| 34 | LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type); | 41 | LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type); |
| 35 | glCompileShader(shader_id); | 42 | glCompileShader(shader_id); |
| 36 | 43 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_util.h b/src/video_core/renderer_opengl/gl_shader_util.h index 03b7548c2..1b770532e 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.h +++ b/src/video_core/renderer_opengl/gl_shader_util.h | |||
| @@ -38,7 +38,7 @@ void LogShaderSource(T... shaders) { | |||
| 38 | * @param source String of the GLSL shader program | 38 | * @param source String of the GLSL shader program |
| 39 | * @param type Type of the shader (GL_VERTEX_SHADER, GL_GEOMETRY_SHADER or GL_FRAGMENT_SHADER) | 39 | * @param type Type of the shader (GL_VERTEX_SHADER, GL_GEOMETRY_SHADER or GL_FRAGMENT_SHADER) |
| 40 | */ | 40 | */ |
| 41 | GLuint LoadShader(const char* source, GLenum type); | 41 | GLuint LoadShader(std::string_view source, GLenum type); |
| 42 | 42 | ||
| 43 | /** | 43 | /** |
| 44 | * Utility function to create and compile an OpenGL GLSL shader program (vertex + fragment shader) | 44 | * Utility function to create and compile an OpenGL GLSL shader program (vertex + fragment shader) |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 14bbc3a1c..b759c2dba 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -21,6 +21,8 @@ | |||
| 21 | #include "core/perf_stats.h" | 21 | #include "core/perf_stats.h" |
| 22 | #include "core/settings.h" | 22 | #include "core/settings.h" |
| 23 | #include "core/telemetry_session.h" | 23 | #include "core/telemetry_session.h" |
| 24 | #include "video_core/host_shaders/opengl_present_frag.h" | ||
| 25 | #include "video_core/host_shaders/opengl_present_vert.h" | ||
| 24 | #include "video_core/morton.h" | 26 | #include "video_core/morton.h" |
| 25 | #include "video_core/renderer_opengl/gl_rasterizer.h" | 27 | #include "video_core/renderer_opengl/gl_rasterizer.h" |
| 26 | #include "video_core/renderer_opengl/gl_shader_manager.h" | 28 | #include "video_core/renderer_opengl/gl_shader_manager.h" |
| @@ -44,46 +46,6 @@ struct Frame { | |||
| 44 | bool is_srgb{}; /// Framebuffer is sRGB or RGB | 46 | bool is_srgb{}; /// Framebuffer is sRGB or RGB |
| 45 | }; | 47 | }; |
| 46 | 48 | ||
| 47 | constexpr char VERTEX_SHADER[] = R"( | ||
| 48 | #version 430 core | ||
| 49 | |||
| 50 | out gl_PerVertex { | ||
| 51 | vec4 gl_Position; | ||
| 52 | }; | ||
| 53 | |||
| 54 | layout (location = 0) in vec2 vert_position; | ||
| 55 | layout (location = 1) in vec2 vert_tex_coord; | ||
| 56 | layout (location = 0) out vec2 frag_tex_coord; | ||
| 57 | |||
| 58 | // This is a truncated 3x3 matrix for 2D transformations: | ||
| 59 | // The upper-left 2x2 submatrix performs scaling/rotation/mirroring. | ||
| 60 | // The third column performs translation. | ||
| 61 | // The third row could be used for projection, which we don't need in 2D. It hence is assumed to | ||
| 62 | // implicitly be [0, 0, 1] | ||
| 63 | layout (location = 0) uniform mat3x2 modelview_matrix; | ||
| 64 | |||
| 65 | void main() { | ||
| 66 | // Multiply input position by the rotscale part of the matrix and then manually translate by | ||
| 67 | // the last column. This is equivalent to using a full 3x3 matrix and expanding the vector | ||
| 68 | // to `vec3(vert_position.xy, 1.0)` | ||
| 69 | gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0); | ||
| 70 | frag_tex_coord = vert_tex_coord; | ||
| 71 | } | ||
| 72 | )"; | ||
| 73 | |||
| 74 | constexpr char FRAGMENT_SHADER[] = R"( | ||
| 75 | #version 430 core | ||
| 76 | |||
| 77 | layout (location = 0) in vec2 frag_tex_coord; | ||
| 78 | layout (location = 0) out vec4 color; | ||
| 79 | |||
| 80 | layout (binding = 0) uniform sampler2D color_texture; | ||
| 81 | |||
| 82 | void main() { | ||
| 83 | color = vec4(texture(color_texture, frag_tex_coord).rgb, 1.0f); | ||
| 84 | } | ||
| 85 | )"; | ||
| 86 | |||
| 87 | constexpr GLint PositionLocation = 0; | 49 | constexpr GLint PositionLocation = 0; |
| 88 | constexpr GLint TexCoordLocation = 1; | 50 | constexpr GLint TexCoordLocation = 1; |
| 89 | constexpr GLint ModelViewMatrixLocation = 0; | 51 | constexpr GLint ModelViewMatrixLocation = 0; |
| @@ -313,10 +275,11 @@ public: | |||
| 313 | } | 275 | } |
| 314 | }; | 276 | }; |
| 315 | 277 | ||
| 316 | RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system, | 278 | RendererOpenGL::RendererOpenGL(Core::System& system_, Core::Frontend::EmuWindow& emu_window_, |
| 317 | Core::Frontend::GraphicsContext& context) | 279 | Tegra::GPU& gpu_, |
| 318 | : RendererBase{emu_window}, emu_window{emu_window}, system{system}, context{context}, | 280 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) |
| 319 | program_manager{device}, has_debug_tool{HasDebugTool()} {} | 281 | : RendererBase{emu_window_, std::move(context_)}, system{system_}, |
| 282 | emu_window{emu_window_}, gpu{gpu_}, program_manager{device}, has_debug_tool{HasDebugTool()} {} | ||
| 320 | 283 | ||
| 321 | RendererOpenGL::~RendererOpenGL() = default; | 284 | RendererOpenGL::~RendererOpenGL() = default; |
| 322 | 285 | ||
| @@ -384,7 +347,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 384 | if (has_debug_tool) { | 347 | if (has_debug_tool) { |
| 385 | glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); | 348 | glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); |
| 386 | Present(0); | 349 | Present(0); |
| 387 | context.SwapBuffers(); | 350 | context->SwapBuffers(); |
| 388 | } | 351 | } |
| 389 | } | 352 | } |
| 390 | 353 | ||
| @@ -460,10 +423,10 @@ void RendererOpenGL::InitOpenGLObjects() { | |||
| 460 | 423 | ||
| 461 | // Create shader programs | 424 | // Create shader programs |
| 462 | OGLShader vertex_shader; | 425 | OGLShader vertex_shader; |
| 463 | vertex_shader.Create(VERTEX_SHADER, GL_VERTEX_SHADER); | 426 | vertex_shader.Create(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER); |
| 464 | 427 | ||
| 465 | OGLShader fragment_shader; | 428 | OGLShader fragment_shader; |
| 466 | fragment_shader.Create(FRAGMENT_SHADER, GL_FRAGMENT_SHADER); | 429 | fragment_shader.Create(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER); |
| 467 | 430 | ||
| 468 | vertex_program.Create(true, false, vertex_shader.handle); | 431 | vertex_program.Create(true, false, vertex_shader.handle); |
| 469 | fragment_program.Create(true, false, fragment_shader.handle); | 432 | fragment_program.Create(true, false, fragment_shader.handle); |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 8b18d32e6..52ea76b7d 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h | |||
| @@ -56,8 +56,9 @@ class FrameMailbox; | |||
| 56 | 56 | ||
| 57 | class RendererOpenGL final : public VideoCore::RendererBase { | 57 | class RendererOpenGL final : public VideoCore::RendererBase { |
| 58 | public: | 58 | public: |
| 59 | explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system, | 59 | explicit RendererOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, |
| 60 | Core::Frontend::GraphicsContext& context); | 60 | Tegra::GPU& gpu, |
| 61 | std::unique_ptr<Core::Frontend::GraphicsContext> context); | ||
| 61 | ~RendererOpenGL() override; | 62 | ~RendererOpenGL() override; |
| 62 | 63 | ||
| 63 | bool Init() override; | 64 | bool Init() override; |
| @@ -93,9 +94,9 @@ private: | |||
| 93 | 94 | ||
| 94 | bool Present(int timeout_ms); | 95 | bool Present(int timeout_ms); |
| 95 | 96 | ||
| 96 | Core::Frontend::EmuWindow& emu_window; | ||
| 97 | Core::System& system; | 97 | Core::System& system; |
| 98 | Core::Frontend::GraphicsContext& context; | 98 | Core::Frontend::EmuWindow& emu_window; |
| 99 | Tegra::GPU& gpu; | ||
| 99 | const Device device; | 100 | const Device device; |
| 100 | 101 | ||
| 101 | StateTracker state_tracker{system}; | 102 | StateTracker state_tracker{system}; |
| @@ -120,7 +121,7 @@ private: | |||
| 120 | std::vector<u8> gl_framebuffer_data; | 121 | std::vector<u8> gl_framebuffer_data; |
| 121 | 122 | ||
| 122 | /// Used for transforming the framebuffer orientation | 123 | /// Used for transforming the framebuffer orientation |
| 123 | Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags; | 124 | Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags{}; |
| 124 | Common::Rectangle<int> framebuffer_crop_rect; | 125 | Common::Rectangle<int> framebuffer_crop_rect; |
| 125 | 126 | ||
| 126 | /// Frame presentation mailbox | 127 | /// Frame presentation mailbox |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 6e49699d0..ae46e0444 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -237,8 +237,10 @@ std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_ext | |||
| 237 | 237 | ||
| 238 | } // Anonymous namespace | 238 | } // Anonymous namespace |
| 239 | 239 | ||
| 240 | RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system) | 240 | RendererVulkan::RendererVulkan(Core::System& system_, Core::Frontend::EmuWindow& emu_window, |
| 241 | : RendererBase(window), system{system} {} | 241 | Tegra::GPU& gpu_, |
| 242 | std::unique_ptr<Core::Frontend::GraphicsContext> context) | ||
| 243 | : RendererBase{emu_window, std::move(context)}, system{system_}, gpu{gpu_} {} | ||
| 242 | 244 | ||
| 243 | RendererVulkan::~RendererVulkan() { | 245 | RendererVulkan::~RendererVulkan() { |
| 244 | ShutDown(); | 246 | ShutDown(); |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index 522b5bff8..13debbbc0 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h | |||
| @@ -38,7 +38,9 @@ struct VKScreenInfo { | |||
| 38 | 38 | ||
| 39 | class RendererVulkan final : public VideoCore::RendererBase { | 39 | class RendererVulkan final : public VideoCore::RendererBase { |
| 40 | public: | 40 | public: |
| 41 | explicit RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system); | 41 | explicit RendererVulkan(Core::System& system, Core::Frontend::EmuWindow& emu_window, |
| 42 | Tegra::GPU& gpu, | ||
| 43 | std::unique_ptr<Core::Frontend::GraphicsContext> context); | ||
| 42 | ~RendererVulkan() override; | 44 | ~RendererVulkan() override; |
| 43 | 45 | ||
| 44 | bool Init() override; | 46 | bool Init() override; |
| @@ -58,6 +60,7 @@ private: | |||
| 58 | void Report() const; | 60 | void Report() const; |
| 59 | 61 | ||
| 60 | Core::System& system; | 62 | Core::System& system; |
| 63 | Tegra::GPU& gpu; | ||
| 61 | 64 | ||
| 62 | Common::DynamicLibrary library; | 65 | Common::DynamicLibrary library; |
| 63 | vk::InstanceDispatch dld; | 66 | vk::InstanceDispatch dld; |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 936f76195..ff1b52eab 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -1443,10 +1443,10 @@ void RasterizerVulkan::UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs) { | |||
| 1443 | } | 1443 | } |
| 1444 | 1444 | ||
| 1445 | void RasterizerVulkan::UpdatePrimitiveTopology(Tegra::Engines::Maxwell3D::Regs& regs) { | 1445 | void RasterizerVulkan::UpdatePrimitiveTopology(Tegra::Engines::Maxwell3D::Regs& regs) { |
| 1446 | if (!state_tracker.TouchPrimitiveTopology()) { | 1446 | const Maxwell::PrimitiveTopology primitive_topology = regs.draw.topology.Value(); |
| 1447 | if (!state_tracker.ChangePrimitiveTopology(primitive_topology)) { | ||
| 1447 | return; | 1448 | return; |
| 1448 | } | 1449 | } |
| 1449 | const Maxwell::PrimitiveTopology primitive_topology = regs.draw.topology.Value(); | ||
| 1450 | scheduler.Record([this, primitive_topology](vk::CommandBuffer cmdbuf) { | 1450 | scheduler.Record([this, primitive_topology](vk::CommandBuffer cmdbuf) { |
| 1451 | cmdbuf.SetPrimitiveTopologyEXT(MaxwellToVK::PrimitiveTopology(device, primitive_topology)); | 1451 | cmdbuf.SetPrimitiveTopologyEXT(MaxwellToVK::PrimitiveTopology(device, primitive_topology)); |
| 1452 | }); | 1452 | }); |
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp index 9151d9fb1..4bd1009f9 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp +++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp | |||
| @@ -42,7 +42,6 @@ Flags MakeInvalidationFlags() { | |||
| 42 | flags[DepthWriteEnable] = true; | 42 | flags[DepthWriteEnable] = true; |
| 43 | flags[DepthCompareOp] = true; | 43 | flags[DepthCompareOp] = true; |
| 44 | flags[FrontFace] = true; | 44 | flags[FrontFace] = true; |
| 45 | flags[PrimitiveTopology] = true; | ||
| 46 | flags[StencilOp] = true; | 45 | flags[StencilOp] = true; |
| 47 | flags[StencilTestEnable] = true; | 46 | flags[StencilTestEnable] = true; |
| 48 | return flags; | 47 | return flags; |
| @@ -112,10 +111,6 @@ void SetupDirtyFrontFace(Tables& tables) { | |||
| 112 | table[OFF(screen_y_control)] = FrontFace; | 111 | table[OFF(screen_y_control)] = FrontFace; |
| 113 | } | 112 | } |
| 114 | 113 | ||
| 115 | void SetupDirtyPrimitiveTopology(Tables& tables) { | ||
| 116 | tables[0][OFF(draw.topology)] = PrimitiveTopology; | ||
| 117 | } | ||
| 118 | |||
| 119 | void SetupDirtyStencilOp(Tables& tables) { | 114 | void SetupDirtyStencilOp(Tables& tables) { |
| 120 | auto& table = tables[0]; | 115 | auto& table = tables[0]; |
| 121 | table[OFF(stencil_front_op_fail)] = StencilOp; | 116 | table[OFF(stencil_front_op_fail)] = StencilOp; |
| @@ -156,13 +151,13 @@ void StateTracker::Initialize() { | |||
| 156 | SetupDirtyDepthWriteEnable(tables); | 151 | SetupDirtyDepthWriteEnable(tables); |
| 157 | SetupDirtyDepthCompareOp(tables); | 152 | SetupDirtyDepthCompareOp(tables); |
| 158 | SetupDirtyFrontFace(tables); | 153 | SetupDirtyFrontFace(tables); |
| 159 | SetupDirtyPrimitiveTopology(tables); | ||
| 160 | SetupDirtyStencilOp(tables); | 154 | SetupDirtyStencilOp(tables); |
| 161 | SetupDirtyStencilTestEnable(tables); | 155 | SetupDirtyStencilTestEnable(tables); |
| 162 | } | 156 | } |
| 163 | 157 | ||
| 164 | void StateTracker::InvalidateCommandBufferState() { | 158 | void StateTracker::InvalidateCommandBufferState() { |
| 165 | system.GPU().Maxwell3D().dirty.flags |= invalidation_flags; | 159 | system.GPU().Maxwell3D().dirty.flags |= invalidation_flags; |
| 160 | current_topology = INVALID_TOPOLOGY; | ||
| 166 | } | 161 | } |
| 167 | 162 | ||
| 168 | } // namespace Vulkan | 163 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h index 54ca0d6c6..13a6ce786 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.h +++ b/src/video_core/renderer_vulkan/vk_state_tracker.h | |||
| @@ -32,7 +32,6 @@ enum : u8 { | |||
| 32 | DepthWriteEnable, | 32 | DepthWriteEnable, |
| 33 | DepthCompareOp, | 33 | DepthCompareOp, |
| 34 | FrontFace, | 34 | FrontFace, |
| 35 | PrimitiveTopology, | ||
| 36 | StencilOp, | 35 | StencilOp, |
| 37 | StencilTestEnable, | 36 | StencilTestEnable, |
| 38 | 37 | ||
| @@ -43,6 +42,8 @@ static_assert(Last <= std::numeric_limits<u8>::max()); | |||
| 43 | } // namespace Dirty | 42 | } // namespace Dirty |
| 44 | 43 | ||
| 45 | class StateTracker { | 44 | class StateTracker { |
| 45 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | ||
| 46 | |||
| 46 | public: | 47 | public: |
| 47 | explicit StateTracker(Core::System& system); | 48 | explicit StateTracker(Core::System& system); |
| 48 | 49 | ||
| @@ -102,10 +103,6 @@ public: | |||
| 102 | return Exchange(Dirty::FrontFace, false); | 103 | return Exchange(Dirty::FrontFace, false); |
| 103 | } | 104 | } |
| 104 | 105 | ||
| 105 | bool TouchPrimitiveTopology() { | ||
| 106 | return Exchange(Dirty::PrimitiveTopology, false); | ||
| 107 | } | ||
| 108 | |||
| 109 | bool TouchStencilOp() { | 106 | bool TouchStencilOp() { |
| 110 | return Exchange(Dirty::StencilOp, false); | 107 | return Exchange(Dirty::StencilOp, false); |
| 111 | } | 108 | } |
| @@ -114,7 +111,15 @@ public: | |||
| 114 | return Exchange(Dirty::StencilTestEnable, false); | 111 | return Exchange(Dirty::StencilTestEnable, false); |
| 115 | } | 112 | } |
| 116 | 113 | ||
| 114 | bool ChangePrimitiveTopology(Maxwell::PrimitiveTopology new_topology) { | ||
| 115 | const bool has_changed = current_topology != new_topology; | ||
| 116 | current_topology = new_topology; | ||
| 117 | return has_changed; | ||
| 118 | } | ||
| 119 | |||
| 117 | private: | 120 | private: |
| 121 | static constexpr auto INVALID_TOPOLOGY = static_cast<Maxwell::PrimitiveTopology>(~0u); | ||
| 122 | |||
| 118 | bool Exchange(std::size_t id, bool new_value) const noexcept { | 123 | bool Exchange(std::size_t id, bool new_value) const noexcept { |
| 119 | auto& flags = system.GPU().Maxwell3D().dirty.flags; | 124 | auto& flags = system.GPU().Maxwell3D().dirty.flags; |
| 120 | const bool is_dirty = flags[id]; | 125 | const bool is_dirty = flags[id]; |
| @@ -124,6 +129,7 @@ private: | |||
| 124 | 129 | ||
| 125 | Core::System& system; | 130 | Core::System& system; |
| 126 | Tegra::Engines::Maxwell3D::DirtyState::Flags invalidation_flags; | 131 | Tegra::Engines::Maxwell3D::DirtyState::Flags invalidation_flags; |
| 132 | Maxwell::PrimitiveTopology current_topology = INVALID_TOPOLOGY; | ||
| 127 | }; | 133 | }; |
| 128 | 134 | ||
| 129 | } // namespace Vulkan | 135 | } // namespace Vulkan |
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index e4739394d..e2bba88dd 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp | |||
| @@ -386,7 +386,8 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 386 | break; | 386 | break; |
| 387 | } | 387 | } |
| 388 | case OpCode::Id::RED: { | 388 | case OpCode::Id::RED: { |
| 389 | UNIMPLEMENTED_IF_MSG(instr.red.type != GlobalAtomicType::U32); | 389 | UNIMPLEMENTED_IF_MSG(instr.red.type != GlobalAtomicType::U32, "type={}", |
| 390 | static_cast<int>(instr.red.type.Value())); | ||
| 390 | const auto [real_address, base_address, descriptor] = | 391 | const auto [real_address, base_address, descriptor] = |
| 391 | TrackGlobalMemory(bb, instr, true, true); | 392 | TrackGlobalMemory(bb, instr, true, true); |
| 392 | if (!real_address || !base_address) { | 393 | if (!real_address || !base_address) { |
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 45f360bdd..4e3a092c7 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | |||
| 6 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | 8 | #include "core/core.h" |
| 8 | #include "core/settings.h" | 9 | #include "core/settings.h" |
| @@ -16,37 +17,46 @@ | |||
| 16 | #include "video_core/video_core.h" | 17 | #include "video_core/video_core.h" |
| 17 | 18 | ||
| 18 | namespace { | 19 | namespace { |
| 19 | std::unique_ptr<VideoCore::RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, | 20 | |
| 20 | Core::System& system, | 21 | std::unique_ptr<VideoCore::RendererBase> CreateRenderer( |
| 21 | Core::Frontend::GraphicsContext& context) { | 22 | Core::System& system, Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu, |
| 23 | std::unique_ptr<Core::Frontend::GraphicsContext> context) { | ||
| 22 | switch (Settings::values.renderer_backend.GetValue()) { | 24 | switch (Settings::values.renderer_backend.GetValue()) { |
| 23 | case Settings::RendererBackend::OpenGL: | 25 | case Settings::RendererBackend::OpenGL: |
| 24 | return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system, context); | 26 | return std::make_unique<OpenGL::RendererOpenGL>(system, emu_window, gpu, |
| 27 | std::move(context)); | ||
| 25 | #ifdef HAS_VULKAN | 28 | #ifdef HAS_VULKAN |
| 26 | case Settings::RendererBackend::Vulkan: | 29 | case Settings::RendererBackend::Vulkan: |
| 27 | return std::make_unique<Vulkan::RendererVulkan>(emu_window, system); | 30 | return std::make_unique<Vulkan::RendererVulkan>(system, emu_window, gpu, |
| 31 | std::move(context)); | ||
| 28 | #endif | 32 | #endif |
| 29 | default: | 33 | default: |
| 30 | return nullptr; | 34 | return nullptr; |
| 31 | } | 35 | } |
| 32 | } | 36 | } |
| 37 | |||
| 33 | } // Anonymous namespace | 38 | } // Anonymous namespace |
| 34 | 39 | ||
| 35 | namespace VideoCore { | 40 | namespace VideoCore { |
| 36 | 41 | ||
| 37 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) { | 42 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) { |
| 43 | std::unique_ptr<Tegra::GPU> gpu; | ||
| 44 | if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) { | ||
| 45 | gpu = std::make_unique<VideoCommon::GPUAsynch>(system); | ||
| 46 | } else { | ||
| 47 | gpu = std::make_unique<VideoCommon::GPUSynch>(system); | ||
| 48 | } | ||
| 49 | |||
| 38 | auto context = emu_window.CreateSharedContext(); | 50 | auto context = emu_window.CreateSharedContext(); |
| 39 | const auto scope = context->Acquire(); | 51 | const auto scope = context->Acquire(); |
| 40 | auto renderer = CreateRenderer(emu_window, system, *context); | 52 | |
| 53 | auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context)); | ||
| 41 | if (!renderer->Init()) { | 54 | if (!renderer->Init()) { |
| 42 | return nullptr; | 55 | return nullptr; |
| 43 | } | 56 | } |
| 44 | 57 | ||
| 45 | if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) { | 58 | gpu->BindRenderer(std::move(renderer)); |
| 46 | return std::make_unique<VideoCommon::GPUAsynch>(system, std::move(renderer), | 59 | return gpu; |
| 47 | std::move(context)); | ||
| 48 | } | ||
| 49 | return std::make_unique<VideoCommon::GPUSynch>(system, std::move(renderer), std::move(context)); | ||
| 50 | } | 60 | } |
| 51 | 61 | ||
| 52 | u16 GetResolutionScaleFactor(const RendererBase& renderer) { | 62 | u16 GetResolutionScaleFactor(const RendererBase& renderer) { |