Compare commits

...

26 Commits

Author SHA1 Message Date
ReinUsesLisp 729ca120e3 shader/shift: Implement SHIFT_RIGHT_{IMM,R}
Shifts a pair of registers to the right and returns the low register.
2020-02-01 21:20:02 -03:00
ReinUsesLisp 017474c3f8 shader/shift: Implement SHF_LEFT_{IMM,R}
Shifts a pair of registers to the left and returns the high register.
2020-02-01 21:19:44 -03:00
bunnei 2db7adc42a Merge pull request #3350 from ReinUsesLisp/atom
shader/memory: Implement ATOM.ADD
2020-01-29 16:49:54 -05:00
bunnei b11aeced18 Merge pull request #3355 from ReinUsesLisp/break-down
texture_cache/surface_base: Fix layered break down
2020-01-29 12:29:56 -05:00
bunnei 91f79225e7 Merge pull request #3358 from ReinUsesLisp/implicit-texture-cache
gl_texture_cache: Silence implicit sign cast warnings
2020-01-29 11:23:50 -05:00
bunnei c457e47297 Merge pull request #3359 from ReinUsesLisp/assert-point-size
gl_shader_decompiler: Remove UNIMPLEMENTED for gl_PointSize
2020-01-28 15:19:51 -05:00
ReinUsesLisp 8178fe8960 gl_shader_decompiler: Remove UNIMPLEMENTED for gl_PointSize
This was implemented by a previous commit and it's no longer required.
2020-01-28 16:32:30 -03:00
bunnei 283f3253bc Merge pull request #3352 from Simek/dark-theme-refinements
GUI: dark themes refinements and QSS cleanup
2020-01-28 14:05:36 -05:00
bunnei bea6327d74 Merge pull request #3354 from ReinUsesLisp/depth-stencil
gl_texture_cache: Properly implement depth/stencil sampling
2020-01-28 12:06:11 -05:00
ReinUsesLisp abae795986 gl_texture_cache: Silence implicit sign cast warnings 2020-01-27 20:59:11 -03:00
bunnei acfb0b4852 Merge pull request #3346 from bunnei/bsd-stub
bsd: Stub several more functions.
2020-01-27 13:06:05 -05:00
ReinUsesLisp f55f6ff9bb texture_cache/surface_base: Fix layered break down
Layered break downs was passing "layer" as a "depth" parameter. This
commit addresses that.
2020-01-26 21:48:07 -03:00
ReinUsesLisp d17dfa6104 gl_texture_cache: Properly implement depth/stencil sampling
This addresses the long standing issue of compatibility vs. core
profiles on OpenGL, properly implementing depth vs. stencil sampling
depending on the texture swizzle.
2020-01-26 21:44:08 -03:00
Bartosz Kaszubowski f68bb4f55e dark themes refinements and cleanup 2020-01-26 11:50:01 +01:00
ReinUsesLisp d95d4ac843 shader/memory: Implement ATOM.ADD
ATOM operates atomically on global memory. For now only add ATOM.ADD
since that's what was found in commercial games.

This asserts for ATOM.ADD.S32 (handling the others as unimplemented),
although ATOM.ADD.U32 shouldn't be any different.

This change forces us to change the default type on SPIR-V storage
buffers from float to uint. We could also alias the buffers, but it's
simpler for now to just use uint. While we are at it, abstract the code
to avoid repetition.
2020-01-26 01:54:24 -03:00
bunnei 2a822f3378 bsd: Stub several more functions.
- Required for Little Town Hero to boot further.
2020-01-25 00:47:15 -05:00
bunnei 05df4a8c94 Merge pull request #3343 from FearlessTobi/ui-tab
yuzu/configuration: create UI tab and move gamelist settings there
2020-01-25 00:40:13 -05:00
bunnei 2b1d66eda3 Merge pull request #3326 from FearlessTobi/port-5039
Port citra-emu/citra#5039: "common/logging: don't use regex for path trimming"
2020-01-24 20:59:57 -05:00
bunnei dfd998216c Merge pull request #3344 from ReinUsesLisp/vk-botw
vk_shader_decompiler: Disable default values on unwritten render targets
2020-01-24 17:31:55 -05:00
bunnei a104b985a8 Merge pull request #3273 from FernandoS27/txd-array
Shader_IR: Implement TXD Array.
2020-01-24 14:02:40 -05:00
bunnei f64adcfc37 Merge pull request #3340 from SciresM/pmdx
loader: provide default arguments (zero byte) to NSOs
2020-01-24 10:31:43 -05:00
ReinUsesLisp 1690f1adba vk_shader_decompiler: Disable default values on unwritten render targets
Some games like The Legend of Zelda: Breath of the Wild assign
render targets without writing them from the fragment shader. This
generates Vulkan validation errors, so silence these I previously
introduced a commit to set "vec4(0, 0, 0, 1)" for these attachments. The
problem is that this is not what games expect. This commit reverts that
change.
2020-01-24 01:16:21 -03:00
FearlessTobi d0e4f1c6f4 yuzu/configuration: create UI tab and move gamelist settings there 2020-01-24 00:15:51 +01:00
BreadFish64 a31ed02ae4 common/logging: don't use regex for path trimming 2020-01-23 23:08:05 +01:00
Michael Scire 5a7eecc3ad loader: provide default arguments (zero byte) to NSOs
Certain newer unity games (Terraria, Pokemon Mystery Dungeon) require
that the argument region be populated. Failure to do so results in
an integer underflow in argument count, and eventually an unmapped
read at 0x800000000. Providing this default fixes this.

Note that the behavior of official software is as yet unverified,
arguments-wise.
2020-01-22 20:14:06 -08:00
Fernando Sahmkow a1667a7b46 Shader_IR: Implement TXD Array.
This commit extends the compilation of TXD to support array samplers on
TXD.
2020-01-04 13:28:02 -04:00
28 changed files with 539 additions and 340 deletions
+112 -110
View File
@@ -2,7 +2,8 @@ QToolTip {
border: 1px solid #76797C;
background-color: #5A7566;
color: white;
padding: 0px; /*remove padding, for fix combobox tooltip.*/
/*remove padding, for fix combobox tooltip.*/
padding: 0;
opacity: 200;
}
@@ -13,7 +14,7 @@ QWidget {
selection-color: #eff0f1;
background-clip: border;
border-image: none;
border: 0px transparent black;
border: 0;
outline: 0;
}
@@ -27,10 +28,10 @@ QWidget:item:selected {
}
QCheckBox {
spacing: 5px;
spacing: 6px;
outline: none;
color: #eff0f1;
margin-bottom: 2px;
margin: 0 2px 1px 0;
}
QCheckBox:disabled {
@@ -163,7 +164,7 @@ QMenuBar::item:selected {
}
QMenuBar::item:pressed {
border: 1px solid #76797C;
border: 1px solid #18465d;
background-color: #3daee9;
color: #eff0f1;
margin-bottom: -1px;
@@ -171,9 +172,9 @@ QMenuBar::item:pressed {
}
QMenu {
border: 1px solid #76797C;
border: 1px solid #434242;
padding: 2px;
color: #eff0f1;
margin: 2px;
}
QMenu::icon {
@@ -190,11 +191,21 @@ QMenu::item:selected {
color: #eff0f1;
}
QMenu::separator {
height: 2px;
background: #76797C;
margin-left: 10px;
margin-right: 5px;
QMenu::item:disabled {
color: #54575B;
}
QMenu::item:disabled:hover,
QMenu::item:disabled:selected {
background-color: #393e43;
color: #666;
}
QMenu::separator,
QMenuBar::separator {
height: 1px;
background-color: #54575B;
margin: 2px 4px 2px 40px;
}
QMenu::indicator {
@@ -203,10 +214,7 @@ QMenu::indicator {
height: 18px;
}
/* non-exclusive indicator = check box style indicator
(see QActionGroup::setExclusive) */
/* non-exclusive indicator = check box style indicator (see QActionGroup::setExclusive) */
QMenu::indicator:non-exclusive:unchecked {
image: url(:/qss_icons/rc/checkbox_unchecked.png);
}
@@ -223,9 +231,7 @@ QMenu::indicator:non-exclusive:checked:selected {
image: url(:/qss_icons/rc/checkbox_checked_disabled.png);
}
/* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */
QMenu::indicator:exclusive:unchecked {
image: url(:/qss_icons/rc/radio_unchecked.png);
}
@@ -243,12 +249,12 @@ QMenu::indicator:exclusive:checked:selected {
}
QMenu::right-arrow {
margin: 5px;
margin-right: 10px;
image: url(:/qss_icons/rc/right_arrow.png)
}
QWidget:disabled {
color: #454545;
color: #4f515b;
background-color: #31363b;
}
@@ -259,23 +265,30 @@ QAbstractItemView {
border-radius: 2px;
}
QWidget:focus,
QMenuBar:focus {
QAbstractItemView:disabled,
QAbstractItemView:read-only {
alternate-background-color: #232629;
}
QWidget:focus {
border: 1px solid #3daee9;
}
QTabWidget:focus,
QCheckBox:focus,
QRadioButton:focus,
QSlider:focus {
QSlider:focus,
QTreeView:focus,
QMenu:focus,
QMenuBar:focus,
QTabBar:focus {
border: none;
}
QLineEdit {
background-color: #232629;
padding: 5px;
border-style: solid;
border: 1px solid #76797C;
border: 1px solid #54575B;
border-radius: 2px;
color: #eff0f1;
}
@@ -285,9 +298,10 @@ QAbstractItemView QLineEdit {
}
QGroupBox {
border: 1px solid #76797C;
border: 1px solid #54575B;
border-radius: 2px;
margin-top: 20px;
margin-top: 12px;
padding-top: 2px;
}
QGroupBox::title {
@@ -295,12 +309,12 @@ QGroupBox::title {
subcontrol-position: top center;
padding-left: 10px;
padding-right: 10px;
padding-top: 10px;
padding-top: 2px;
}
QAbstractScrollArea {
border-radius: 2px;
border: 1px solid #76797C;
border: 1px solid #54575B;
background-color: transparent;
}
@@ -319,7 +333,7 @@ QScrollBar::handle:horizontal {
}
QScrollBar::add-line:horizontal {
margin: 0px 3px 0px 3px;
margin: 0 3px;
border-image: url(:/qss_icons/rc/right_arrow_disabled.png);
width: 10px;
height: 10px;
@@ -328,7 +342,7 @@ QScrollBar::add-line:horizontal {
}
QScrollBar::sub-line:horizontal {
margin: 0px 3px 0px 3px;
margin: 0 3px;
border-image: url(:/qss_icons/rc/left_arrow_disabled.png);
height: 10px;
width: 10px;
@@ -379,7 +393,7 @@ QScrollBar::handle:vertical {
}
QScrollBar::sub-line:vertical {
margin: 3px 0px 3px 0px;
margin: 3px 0;
border-image: url(:/qss_icons/rc/up_arrow_disabled.png);
height: 10px;
width: 10px;
@@ -388,7 +402,7 @@ QScrollBar::sub-line:vertical {
}
QScrollBar::add-line:vertical {
margin: 3px 0px 3px 0px;
margin: 3px 0;
border-image: url(:/qss_icons/rc/down_arrow_disabled.png);
height: 10px;
width: 10px;
@@ -427,15 +441,14 @@ QScrollBar::sub-page:vertical {
QTextEdit {
background-color: #232629;
color: #eff0f1;
border: 1px solid #76797C;
border: 1px solid #54575B;
}
QPlainTextEdit {
background-color: #232629;
;
color: #eff0f1;
border-radius: 2px;
border: 1px solid #76797C;
border: 1px solid #54575B;
}
QHeaderView::section {
@@ -467,15 +480,6 @@ QMainWindow::separator:hover {
spacing: 2px;
}
QMenu::separator {
height: 1px;
background-color: #76797C;
color: white;
padding-left: 4px;
margin-left: 10px;
margin-right: 5px;
}
QFrame {
border-radius: 2px;
border: 1px solid #76797C;
@@ -518,25 +522,19 @@ QToolButton#qt_toolbar_ext_button {
QPushButton {
color: #eff0f1;
background-color: #31363b;
border-width: 1px;
border-color: #76797C;
border-color: #54575B;
border-style: solid;
padding: 5px;
padding: 6px 4px;
border-radius: 2px;
outline: none;
min-width: 100px;
background-color: #232629;
}
QPushButton:disabled {
background-color: #31363b;
border-width: 1px;
border-color: #454545;
border-style: solid;
padding-top: 5px;
padding-bottom: 5px;
padding-left: 10px;
padding-right: 10px;
border-radius: 2px;
color: #454545;
}
@@ -553,11 +551,11 @@ QPushButton:pressed {
QComboBox {
selection-background-color: #3daee9;
border-style: solid;
border: 1px solid #76797C;
border: 1px solid #54575B;
border-radius: 2px;
padding: 5px;
padding: 4px 6px;
min-width: 75px;
background-color: #232629;
}
QPushButton:checked {
@@ -571,8 +569,7 @@ QAbstractSpinBox:hover,
QLineEdit:hover,
QTextEdit:hover,
QPlainTextEdit:hover,
QAbstractView:hover,
QTreeView:hover {
QAbstractView:hover {
border: 1px solid #3daee9;
color: #eff0f1;
}
@@ -591,6 +588,7 @@ QComboBox QAbstractItemView {
QComboBox::drop-down {
subcontrol-origin: padding;
subcontrol-position: top right;
left: -6px;
width: 15px;
border-left-width: 0px;
border-left-color: darkgray;
@@ -610,8 +608,8 @@ QComboBox::down-arrow:focus {
}
QAbstractSpinBox {
padding: 5px;
border: 1px solid #76797C;
padding: 4px 6px;
border: 1px solid #54575B;
background-color: #232629;
color: #eff0f1;
border-radius: 2px;
@@ -622,12 +620,14 @@ QAbstractSpinBox:up-button {
background-color: transparent;
subcontrol-origin: border;
subcontrol-position: center right;
left: -6px;
}
QAbstractSpinBox:down-button {
background-color: transparent;
subcontrol-origin: border;
subcontrol-position: center left;
right: -6px;
}
QAbstractSpinBox::up-arrow,
@@ -654,22 +654,27 @@ QAbstractSpinBox::down-arrow:hover {
image: url(:/qss_icons/rc/down_arrow.png);
}
QLabel {
border: 0px solid black;
QLabel,
QTabWidget {
border: 0;
}
QTabWidget {
border: 0px transparent black;
padding-top: 1px;
}
QTabWidget::pane {
border: 1px solid #76797C;
padding: 5px;
margin: 0px;
position: absolute;
top: -1px;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
border-bottom-left-radius: 2px;
}
QTabWidget::tab-bar {
/* left: 5px; move to the right by 5px */
overflow: visible;
}
QTabBar {
@@ -677,10 +682,6 @@ QTabBar {
border-radius: 3px;
}
QTabBar:focus {
border: 0px transparent black;
}
QTabBar::close-button {
image: url(:/qss_icons/rc/close.png);
background: transparent;
@@ -696,36 +697,33 @@ QTabBar::close-button:pressed {
background: transparent;
}
/* TOP TABS */
QTabBar::tab:top {
color: #eff0f1;
border: 1px solid #76797C;
border-bottom: 2px transparent;
background-color: #31363b;
padding: 4px 16px 2px;
min-width: 38px;
border: 1px solid #54575B;
background-color: #2a2f33;
padding: 4px 16px 5px;
min-width: 36px;
border-top-left-radius: 2px;
border-top-right-radius: 2px;
}
QTabBar::tab:top:selected {
color: #eff0f1;
background-color: #54575B;
border: 1px solid #76797C;
border-bottom: 2px solid #3daee9;
border-top-left-radius: 2px;
border-top-right-radius: 2px;
border-color: #76797C;
background-color: #31363b;
border-bottom-color: #31363b;
}
QTabBar::tab:top:!selected {
margin-top: 1px;
border-bottom-color: #76797C;
}
QTabBar::tab:top:!selected:hover {
background-color: #3daee9;
}
/* BOTTOM TABS */
QTabBar::tab:bottom {
color: #eff0f1;
border: 1px solid #76797C;
@@ -750,9 +748,7 @@ QTabBar::tab:bottom:!selected:hover {
background-color: #3daee9;
}
/* LEFT TABS */
QTabBar::tab:left {
color: #eff0f1;
border: 1px solid #76797C;
@@ -777,9 +773,7 @@ QTabBar::tab:left:!selected:hover {
background-color: #3daee9;
}
/* RIGHT TABS */
QTabBar::tab:right {
color: #eff0f1;
border: 1px solid #76797C;
@@ -847,7 +841,7 @@ QDockWidget::float-button:pressed {
QTreeView,
QListView {
border: 1px solid #76797C;
border: 1px solid #54575B;
background-color: #232629;
}
@@ -978,8 +972,8 @@ QSlider::handle:vertical {
}
QToolButton {
background-color: transparent;
border: 1px transparent #76797C;
background-color: #232629;
border: 1px solid #54575B;
border-radius: 2px;
margin: 3px;
padding: 5px;
@@ -988,7 +982,6 @@ QToolButton {
QToolButton[popupMode="1"] {
/* only for MenuButtonPopup */
padding-right: 20px;
/* make way for the popup button */
border: 1px #76797C;
border-radius: 5px;
}
@@ -996,7 +989,6 @@ QToolButton[popupMode="1"] {
QToolButton[popupMode="2"] {
/* only for InstantPopup */
padding-right: 10px;
/* make way for the popup button */
border: 1px #76797C;
}
@@ -1015,19 +1007,14 @@ QToolButton::menu-button:pressed {
padding: 5px;
}
/* the subcontrol below is used only in the InstantPopup or DelayedPopup mode */
QToolButton::menu-indicator {
image: url(:/qss_icons/rc/down_arrow.png);
top: -7px;
left: -2px;
/* shift it a bit */
}
/* the subcontrols below are used only in the MenuButtonPopup mode */
QToolButton::menu-button {
border: 1px transparent #76797C;
border-top-right-radius: 6px;
@@ -1052,14 +1039,22 @@ QPushButton::menu-indicator {
}
QTableView {
border: 1px solid #76797C;
border: 1px solid #54575B;
gridline-color: #31363b;
background-color: #232629;
}
QTreeView:disabled {
background-color: #1f2225;
}
QTableView,
QHeaderView {
border-radius: 0px;
border-radius: 0;
}
QListView:focus {
border-color: #54575B;
}
QTableView::item:pressed,
@@ -1088,7 +1083,7 @@ QHeaderView::section {
background-color: #232629;
color: #eff0f1;
padding: 0 5px;
border: 1px solid #403F3F;
border: 1px solid #434242;
border-bottom: 0;
border-radius: 0px;
text-align: center;
@@ -1118,9 +1113,7 @@ QHeaderView::section:checked {
background-color: #334e5e;
}
/* style the sort indicator */
/* sort indicator */
QHeaderView::down-arrow {
image: url(:/qss_icons/rc/down_arrow.png);
}
@@ -1150,14 +1143,13 @@ QToolBox::tab {
}
QToolBox::tab:selected {
/* italicize selected tabs */
font: italic;
background-color: #31363b;
border-color: #3daee9;
}
QStatusBar::item {
border: 0px transparent dark;
border: 0;
}
QFrame[height="3"],
@@ -1194,7 +1186,6 @@ QProgressBar::chunk {
QDateEdit {
selection-background-color: #3daee9;
border-style: solid;
border: 1px solid #3375A3;
border-radius: 2px;
padding: 1px;
@@ -1218,7 +1209,7 @@ QDateEdit::drop-down {
subcontrol-origin: padding;
subcontrol-position: top right;
width: 15px;
border-left-width: 0px;
border-left-width: 0;
border-left-color: darkgray;
border-left-style: solid;
border-top-right-radius: 3px;
@@ -1234,3 +1225,14 @@ QDateEdit::down-arrow:hover,
QDateEdit::down-arrow:focus {
image: url(:/qss_icons/rc/down_arrow.png);
}
QComboBox:disabled,
QPushButton:disabled,
QAbstractSpinBox:disabled,
QDateEdit:disabled,
QLineEdit:disabled,
QTextEdit:disabled,
QToolButton:disabled,
QPlainTextEdit:disabled {
background-color: #2b2e31;
}
+1 -1
View File
@@ -120,7 +120,7 @@ private:
duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin);
entry.log_class = log_class;
entry.log_level = log_level;
entry.filename = Common::TrimSourcePath(filename);
entry.filename = filename;
entry.line_num = line_nr;
entry.function = function;
entry.message = std::move(message);
+1 -1
View File
@@ -23,7 +23,7 @@ struct Entry {
std::chrono::microseconds timestamp;
Class log_class;
Level log_level;
std::string filename;
const char* filename;
unsigned int line_num;
std::string function;
std::string message;
+21 -12
View File
@@ -9,6 +9,15 @@
namespace Log {
// trims up to and including the last of ../, ..\, src/, src\ in a string
constexpr const char* TrimSourcePath(std::string_view source) {
const auto rfind = [source](const std::string_view match) {
return source.rfind(match) == source.npos ? 0 : (source.rfind(match) + match.size());
};
auto idx = std::max({rfind("src/"), rfind("src\\"), rfind("../"), rfind("..\\")});
return source.data() + idx;
}
/// Specifies the severity or level of detail of the log message.
enum class Level : u8 {
Trace, ///< Extremely detailed and repetitive debugging information that is likely to
@@ -141,24 +150,24 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig
#ifdef _DEBUG
#define LOG_TRACE(log_class, ...) \
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Trace, __FILE__, __LINE__, \
__func__, __VA_ARGS__)
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Trace, \
::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
#else
#define LOG_TRACE(log_class, fmt, ...) (void(0))
#endif
#define LOG_DEBUG(log_class, ...) \
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Debug, __FILE__, __LINE__, \
__func__, __VA_ARGS__)
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Debug, \
::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
#define LOG_INFO(log_class, ...) \
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Info, __FILE__, __LINE__, \
__func__, __VA_ARGS__)
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Info, \
::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
#define LOG_WARNING(log_class, ...) \
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Warning, __FILE__, __LINE__, \
__func__, __VA_ARGS__)
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Warning, \
::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
#define LOG_ERROR(log_class, ...) \
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Error, __FILE__, __LINE__, \
__func__, __VA_ARGS__)
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Error, \
::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
#define LOG_CRITICAL(log_class, ...) \
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Critical, __FILE__, __LINE__, \
__func__, __VA_ARGS__)
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Critical, \
::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
-22
View File
@@ -223,26 +223,4 @@ std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buff
return std::u16string(buffer.begin(), buffer.begin() + len);
}
const char* TrimSourcePath(const char* path, const char* root) {
const char* p = path;
while (*p != '\0') {
const char* next_slash = p;
while (*next_slash != '\0' && *next_slash != '/' && *next_slash != '\\') {
++next_slash;
}
bool is_src = Common::ComparePartialString(p, next_slash, root);
p = next_slash;
if (*p != '\0') {
++p;
}
if (is_src) {
path = p;
}
}
return path;
}
} // namespace Common
+44 -4
View File
@@ -42,6 +42,26 @@ void BSD::Socket(Kernel::HLERequestContext& ctx) {
rb.Push<u32>(0); // bsd errno
}
void BSD::Select(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0); // ret
rb.Push<u32>(0); // bsd errno
}
void BSD::Bind(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0); // ret
rb.Push<u32>(0); // bsd errno
}
void BSD::Connect(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
@@ -52,6 +72,26 @@ void BSD::Connect(Kernel::HLERequestContext& ctx) {
rb.Push<u32>(0); // bsd errno
}
void BSD::Listen(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0); // ret
rb.Push<u32>(0); // bsd errno
}
void BSD::SetSockOpt(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0); // ret
rb.Push<u32>(0); // bsd errno
}
void BSD::SendTo(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
@@ -80,7 +120,7 @@ BSD::BSD(const char* name) : ServiceFramework(name) {
{2, &BSD::Socket, "Socket"},
{3, nullptr, "SocketExempt"},
{4, nullptr, "Open"},
{5, nullptr, "Select"},
{5, &BSD::Select, "Select"},
{6, nullptr, "Poll"},
{7, nullptr, "Sysctl"},
{8, nullptr, "Recv"},
@@ -88,15 +128,15 @@ BSD::BSD(const char* name) : ServiceFramework(name) {
{10, nullptr, "Send"},
{11, &BSD::SendTo, "SendTo"},
{12, nullptr, "Accept"},
{13, nullptr, "Bind"},
{13, &BSD::Bind, "Bind"},
{14, &BSD::Connect, "Connect"},
{15, nullptr, "GetPeerName"},
{16, nullptr, "GetSockName"},
{17, nullptr, "GetSockOpt"},
{18, nullptr, "Listen"},
{18, &BSD::Listen, "Listen"},
{19, nullptr, "Ioctl"},
{20, nullptr, "Fcntl"},
{21, nullptr, "SetSockOpt"},
{21, &BSD::SetSockOpt, "SetSockOpt"},
{22, nullptr, "Shutdown"},
{23, nullptr, "ShutdownAllSockets"},
{24, nullptr, "Write"},
+4
View File
@@ -18,7 +18,11 @@ private:
void RegisterClient(Kernel::HLERequestContext& ctx);
void StartMonitoring(Kernel::HLERequestContext& ctx);
void Socket(Kernel::HLERequestContext& ctx);
void Select(Kernel::HLERequestContext& ctx);
void Bind(Kernel::HLERequestContext& ctx);
void Connect(Kernel::HLERequestContext& ctx);
void Listen(Kernel::HLERequestContext& ctx);
void SetSockOpt(Kernel::HLERequestContext& ctx);
void SendTo(Kernel::HLERequestContext& ctx);
void Close(Kernel::HLERequestContext& ctx);
+8 -3
View File
@@ -97,7 +97,8 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
if (nso_header.IsSegmentCompressed(i)) {
data = DecompressSegment(data, nso_header.segments[i]);
}
program_image.resize(nso_header.segments[i].location + data.size());
program_image.resize(nso_header.segments[i].location +
PageAlignSize(static_cast<u32>(data.size())));
std::memcpy(program_image.data() + nso_header.segments[i].location, data.data(),
data.size());
codeset.segments[i].addr = nso_header.segments[i].location;
@@ -105,8 +106,12 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
codeset.segments[i].size = PageAlignSize(static_cast<u32>(data.size()));
}
if (should_pass_arguments && !Settings::values.program_args.empty()) {
const auto arg_data = Settings::values.program_args;
if (should_pass_arguments) {
std::vector<u8> arg_data{Settings::values.program_args.begin(),
Settings::values.program_args.end()};
if (arg_data.empty()) {
arg_data.resize(NSO_ARGUMENT_DEFAULT_SIZE);
}
codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE;
NSOArgumentHeader args_header{
NSO_ARGUMENT_DATA_ALLOCATION_SIZE, static_cast<u32_le>(arg_data.size()), {}};
+2
View File
@@ -56,6 +56,8 @@ static_assert(sizeof(NSOHeader) == 0x100, "NSOHeader has incorrect size.");
static_assert(std::is_trivially_copyable_v<NSOHeader>, "NSOHeader must be trivially copyable.");
constexpr u64 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000;
// NOTE: Official software default argument state is unverified.
constexpr u64 NSO_ARGUMENT_DEFAULT_SIZE = 1;
struct NSOArgumentHeader {
u32_le allocated_size;
+50
View File
@@ -227,6 +227,28 @@ enum class AtomicOp : u64 {
Exch = 8,
};
enum class GlobalAtomicOp : u64 {
Add = 0,
Min = 1,
Max = 2,
Inc = 3,
Dec = 4,
And = 5,
Or = 6,
Xor = 7,
Exch = 8,
SafeAdd = 10,
};
enum class GlobalAtomicType : u64 {
U32 = 0,
S32 = 1,
U64 = 2,
F32_FTZ_RN = 3,
F16x2_FTZ_RN = 4,
S64 = 5,
};
enum class UniformType : u64 {
UnsignedByte = 0,
SignedByte = 1,
@@ -602,6 +624,19 @@ enum class ShuffleOperation : u64 {
Bfly = 3, // shuffleXorNV
};
enum class ShfType : u64 {
Bits32 = 0,
U64 = 2,
S64 = 3,
};
enum class ShfXmode : u64 {
None = 0,
HI = 1,
X = 2,
XHI = 3,
};
union Instruction {
constexpr Instruction& operator=(const Instruction& instr) {
value = instr.value;
@@ -753,6 +788,13 @@ union Instruction {
BitField<39, 1, u64> wrap;
} shr;
union {
BitField<37, 2, ShfType> type;
BitField<48, 2, ShfXmode> xmode;
BitField<50, 1, u64> wrap;
BitField<20, 6, u64> immediate;
} shf;
union {
BitField<39, 5, u64> shift_amount;
BitField<48, 1, u64> negate_b;
@@ -957,6 +999,12 @@ union Instruction {
BitField<46, 2, u64> cache_mode;
} stg;
union {
BitField<52, 4, GlobalAtomicOp> operation;
BitField<49, 3, GlobalAtomicType> type;
BitField<28, 20, s64> offset;
} atom;
union {
BitField<52, 4, AtomicOp> operation;
BitField<28, 2, AtomicType> type;
@@ -1690,6 +1738,7 @@ public:
ST_S,
ST, // Store in generic memory
STG, // Store in global memory
ATOM, // Atomic operation on global memory
ATOMS, // Atomic operation on shared memory
AL2P, // Transforms attribute memory into physical memory
TEX,
@@ -1994,6 +2043,7 @@ private:
INST("1110111101010---", Id::ST_L, Type::Memory, "ST_L"),
INST("101-------------", Id::ST, Type::Memory, "ST"),
INST("1110111011011---", Id::STG, Type::Memory, "STG"),
INST("11101101--------", Id::ATOM, Type::Memory, "ATOM"),
INST("11101100--------", Id::ATOMS, Type::Memory, "ATOMS"),
INST("1110111110100---", Id::AL2P, Type::Memory, "AL2P"),
INST("110000----111---", Id::TEX, Type::Texture, "TEX"),
@@ -1019,7 +1019,6 @@ private:
}
return {{"gl_ViewportIndex", Type::Int}};
case 3:
UNIMPLEMENTED_MSG("Requires some state changes for gl_PointSize to work in shader");
return {{"gl_PointSize", Type::Float}};
}
return {};
@@ -1858,10 +1857,7 @@ private:
template <const std::string_view& opname, Type type>
Expression Atomic(Operation operation) {
ASSERT(stage == ShaderType::Compute);
auto& smem = std::get<SmemNode>(*operation[0]);
return {fmt::format("atomic{}(smem[{} >> 2], {})", opname, Visit(smem.GetAddress()).AsInt(),
return {fmt::format("atomic{}({}, {})", opname, Visit(operation[0]).GetCode(),
Visit(operation[1]).As(type)),
type};
}
@@ -176,6 +176,19 @@ GLint GetSwizzleSource(SwizzleSource source) {
return GL_NONE;
}
GLenum GetComponent(PixelFormat format, bool is_first) {
switch (format) {
case PixelFormat::Z24S8:
case PixelFormat::Z32FS8:
return is_first ? GL_DEPTH_COMPONENT : GL_STENCIL_INDEX;
case PixelFormat::S8Z24:
return is_first ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT;
default:
UNREACHABLE();
return GL_DEPTH_COMPONENT;
}
}
void ApplyTextureDefaults(const SurfaceParams& params, GLuint texture) {
if (params.IsBuffer()) {
return;
@@ -184,7 +197,7 @@ void ApplyTextureDefaults(const SurfaceParams& params, GLuint texture) {
glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTextureParameteri(texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTextureParameteri(texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTextureParameteri(texture, GL_TEXTURE_MAX_LEVEL, params.num_levels - 1);
glTextureParameteri(texture, GL_TEXTURE_MAX_LEVEL, static_cast<GLint>(params.num_levels - 1));
if (params.num_levels == 1) {
glTextureParameterf(texture, GL_TEXTURE_LOD_BIAS, 1000.0f);
}
@@ -416,11 +429,21 @@ void CachedSurfaceView::ApplySwizzle(SwizzleSource x_source, SwizzleSource y_sou
if (new_swizzle == swizzle)
return;
swizzle = new_swizzle;
const std::array<GLint, 4> gl_swizzle = {GetSwizzleSource(x_source), GetSwizzleSource(y_source),
GetSwizzleSource(z_source),
GetSwizzleSource(w_source)};
const std::array gl_swizzle = {GetSwizzleSource(x_source), GetSwizzleSource(y_source),
GetSwizzleSource(z_source), GetSwizzleSource(w_source)};
const GLuint handle = GetTexture();
glTextureParameteriv(handle, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle.data());
const PixelFormat format = surface.GetSurfaceParams().pixel_format;
switch (format) {
case PixelFormat::Z24S8:
case PixelFormat::Z32FS8:
case PixelFormat::S8Z24:
glTextureParameteri(handle, GL_DEPTH_STENCIL_TEXTURE_MODE,
GetComponent(format, x_source == SwizzleSource::R));
break;
default:
glTextureParameteriv(handle, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle.data());
break;
}
}
OGLTextureView CachedSurfaceView::CreateTextureView() const {
@@ -529,8 +552,11 @@ void TextureCacheOpenGL::ImageBlit(View& src_view, View& dst_view,
const Common::Rectangle<u32>& dst_rect = copy_config.dst_rect;
const bool is_linear = copy_config.filter == Tegra::Engines::Fermi2D::Filter::Linear;
glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, dst_rect.left,
dst_rect.top, dst_rect.right, dst_rect.bottom, buffers,
glBlitFramebuffer(static_cast<GLint>(src_rect.left), static_cast<GLint>(src_rect.top),
static_cast<GLint>(src_rect.right), static_cast<GLint>(src_rect.bottom),
static_cast<GLint>(dst_rect.left), static_cast<GLint>(dst_rect.top),
static_cast<GLint>(dst_rect.right), static_cast<GLint>(dst_rect.bottom),
buffers,
is_linear && (buffers == GL_COLOR_BUFFER_BIT) ? GL_LINEAR : GL_NEAREST);
}
@@ -325,9 +325,6 @@ VKPipelineCache::DecompileShaders(const GraphicsPipelineCacheKey& key) {
specialization.tessellation.primitive = fixed_state.tessellation.primitive;
specialization.tessellation.spacing = fixed_state.tessellation.spacing;
specialization.tessellation.clockwise = fixed_state.tessellation.clockwise;
for (const auto& rt : key.renderpass_params.color_attachments) {
specialization.enabled_rendertargets.set(rt.index);
}
SPIRVProgram program;
std::vector<vk::DescriptorSetLayoutBinding> bindings;
@@ -542,11 +542,10 @@ private:
return;
}
for (u32 rt = 0; rt < static_cast<u32>(frag_colors.size()); ++rt) {
if (!specialization.enabled_rendertargets[rt]) {
for (u32 rt = 0; rt < static_cast<u32>(std::size(frag_colors)); ++rt) {
if (!IsRenderTargetEnabled(rt)) {
continue;
}
const Id id = AddGlobalVariable(OpVariable(t_out_float4, spv::StorageClass::Output));
Name(id, fmt::format("frag_color{}", rt));
Decorate(id, spv::Decoration::Location, rt);
@@ -852,6 +851,15 @@ private:
return binding;
}
bool IsRenderTargetEnabled(u32 rt) const {
for (u32 component = 0; component < 4; ++component) {
if (header.ps.IsColorComponentOutputEnabled(rt, component)) {
return true;
}
}
return false;
}
bool IsInputAttributeArray() const {
return stage == ShaderType::TesselationControl || stage == ShaderType::TesselationEval ||
stage == ShaderType::Geometry;
@@ -1115,15 +1123,7 @@ private:
}
if (const auto gmem = std::get_if<GmemNode>(&*node)) {
const Id gmem_buffer = global_buffers.at(gmem->GetDescriptor());
const Id real = AsUint(Visit(gmem->GetRealAddress()));
const Id base = AsUint(Visit(gmem->GetBaseAddress()));
Id offset = OpISub(t_uint, real, base);
offset = OpUDiv(t_uint, offset, Constant(t_uint, 4U));
return {OpLoad(t_float,
OpAccessChain(t_gmem_float, gmem_buffer, Constant(t_uint, 0U), offset)),
Type::Float};
return {OpLoad(t_uint, GetGlobalMemoryPointer(*gmem)), Type::Uint};
}
if (const auto lmem = std::get_if<LmemNode>(&*node)) {
@@ -1134,10 +1134,7 @@ private:
}
if (const auto smem = std::get_if<SmemNode>(&*node)) {
Id address = AsUint(Visit(smem->GetAddress()));
address = OpShiftRightLogical(t_uint, address, Constant(t_uint, 2U));
const Id pointer = OpAccessChain(t_smem_uint, shared_memory, address);
return {OpLoad(t_uint, pointer), Type::Uint};
return {OpLoad(t_uint, GetSharedMemoryPointer(*smem)), Type::Uint};
}
if (const auto internal_flag = std::get_if<InternalFlagNode>(&*node)) {
@@ -1331,20 +1328,10 @@ private:
target = {OpAccessChain(t_prv_float, local_memory, address), Type::Float};
} else if (const auto smem = std::get_if<SmemNode>(&*dest)) {
ASSERT(stage == ShaderType::Compute);
Id address = AsUint(Visit(smem->GetAddress()));
address = OpShiftRightLogical(t_uint, address, Constant(t_uint, 2U));
target = {OpAccessChain(t_smem_uint, shared_memory, address), Type::Uint};
target = {GetSharedMemoryPointer(*smem), Type::Uint};
} else if (const auto gmem = std::get_if<GmemNode>(&*dest)) {
const Id real = AsUint(Visit(gmem->GetRealAddress()));
const Id base = AsUint(Visit(gmem->GetBaseAddress()));
const Id diff = OpISub(t_uint, real, base);
const Id offset = OpShiftRightLogical(t_uint, diff, Constant(t_uint, 2));
const Id gmem_buffer = global_buffers.at(gmem->GetDescriptor());
target = {OpAccessChain(t_gmem_float, gmem_buffer, Constant(t_uint, 0), offset),
Type::Float};
target = {GetGlobalMemoryPointer(*gmem), Type::Uint};
} else {
UNIMPLEMENTED();
@@ -1796,11 +1783,16 @@ private:
return {};
}
Expression UAtomicAdd(Operation operation) {
const auto& smem = std::get<SmemNode>(*operation[0]);
Id address = AsUint(Visit(smem.GetAddress()));
address = OpShiftRightLogical(t_uint, address, Constant(t_uint, 2U));
const Id pointer = OpAccessChain(t_smem_uint, shared_memory, address);
Expression AtomicAdd(Operation operation) {
Id pointer;
if (const auto smem = std::get_if<SmemNode>(&*operation[0])) {
pointer = GetSharedMemoryPointer(*smem);
} else if (const auto gmem = std::get_if<GmemNode>(&*operation[0])) {
pointer = GetGlobalMemoryPointer(*gmem);
} else {
UNREACHABLE();
return {Constant(t_uint, 0), Type::Uint};
}
const Id scope = Constant(t_uint, static_cast<u32>(spv::Scope::Device));
const Id semantics = Constant(t_uint, 0U);
@@ -1889,19 +1881,14 @@ private:
// rendertargets/components are skipped in the register assignment.
u32 current_reg = 0;
for (u32 rt = 0; rt < Maxwell::NumRenderTargets; ++rt) {
if (!specialization.enabled_rendertargets[rt]) {
// Skip rendertargets that are not enabled
continue;
}
// TODO(Subv): Figure out how dual-source blending is configured in the Switch.
for (u32 component = 0; component < 4; ++component) {
const Id pointer = AccessElement(t_out_float, frag_colors.at(rt), component);
if (header.ps.IsColorComponentOutputEnabled(rt, component)) {
OpStore(pointer, SafeGetRegister(current_reg));
++current_reg;
} else {
OpStore(pointer, component == 3 ? v_float_one : v_float_zero);
if (!header.ps.IsColorComponentOutputEnabled(rt, component)) {
continue;
}
const Id pointer = AccessElement(t_out_float, frag_colors[rt], component);
OpStore(pointer, SafeGetRegister(current_reg));
++current_reg;
}
}
if (header.ps.omap.depth) {
@@ -2240,6 +2227,22 @@ private:
return {};
}
Id GetGlobalMemoryPointer(const GmemNode& gmem) {
const Id real = AsUint(Visit(gmem.GetRealAddress()));
const Id base = AsUint(Visit(gmem.GetBaseAddress()));
const Id diff = OpISub(t_uint, real, base);
const Id offset = OpShiftRightLogical(t_uint, diff, Constant(t_uint, 2));
const Id buffer = global_buffers.at(gmem.GetDescriptor());
return OpAccessChain(t_gmem_uint, buffer, Constant(t_uint, 0), offset);
}
Id GetSharedMemoryPointer(const SmemNode& smem) {
ASSERT(stage == ShaderType::Compute);
Id address = AsUint(Visit(smem.GetAddress()));
address = OpShiftRightLogical(t_uint, address, Constant(t_uint, 2U));
return OpAccessChain(t_smem_uint, shared_memory, address);
}
static constexpr std::array operation_decompilers = {
&SPIRVDecompiler::Assign,
@@ -2386,7 +2389,7 @@ private:
&SPIRVDecompiler::AtomicImageXor,
&SPIRVDecompiler::AtomicImageExchange,
&SPIRVDecompiler::UAtomicAdd,
&SPIRVDecompiler::AtomicAdd,
&SPIRVDecompiler::Branch,
&SPIRVDecompiler::BranchIndirect,
@@ -2482,9 +2485,9 @@ private:
Id t_smem_uint{};
const Id t_gmem_float = TypePointer(spv::StorageClass::StorageBuffer, t_float);
const Id t_gmem_uint = TypePointer(spv::StorageClass::StorageBuffer, t_uint);
const Id t_gmem_array =
Name(Decorate(TypeRuntimeArray(t_float), spv::Decoration::ArrayStride, 4U), "GmemArray");
Name(Decorate(TypeRuntimeArray(t_uint), spv::Decoration::ArrayStride, 4U), "GmemArray");
const Id t_gmem_struct = MemberDecorate(
Decorate(TypeStruct(t_gmem_array), spv::Decoration::Block), 0, spv::Decoration::Offset, 0);
const Id t_gmem_ssbo = TypePointer(spv::StorageClass::StorageBuffer, t_gmem_struct);
@@ -102,9 +102,6 @@ struct Specialization final {
Maxwell::TessellationSpacing spacing{};
bool clockwise{};
} tessellation;
// Fragment specific
std::bitset<8> enabled_rendertargets;
};
// Old gcc versions don't consider this trivially copyable.
// static_assert(std::is_trivially_copyable_v<Specialization>);
+21 -1
View File
@@ -19,6 +19,8 @@ namespace VideoCommon::Shader {
using Tegra::Shader::AtomicOp;
using Tegra::Shader::AtomicType;
using Tegra::Shader::Attribute;
using Tegra::Shader::GlobalAtomicOp;
using Tegra::Shader::GlobalAtomicType;
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
using Tegra::Shader::Register;
@@ -335,6 +337,24 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
}
break;
}
case OpCode::Id::ATOM: {
UNIMPLEMENTED_IF_MSG(instr.atom.operation != GlobalAtomicOp::Add, "operation={}",
static_cast<int>(instr.atom.operation.Value()));
UNIMPLEMENTED_IF_MSG(instr.atom.type != GlobalAtomicType::S32, "type={}",
static_cast<int>(instr.atom.type.Value()));
const auto [real_address, base_address, descriptor] =
TrackGlobalMemory(bb, instr, true, true);
if (!real_address || !base_address) {
// Tracking failed, skip atomic.
break;
}
Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor);
Node value = Operation(OperationCode::AtomicAdd, std::move(gmem), GetRegister(instr.gpr20));
SetRegister(bb, instr.gpr0, std::move(value));
break;
}
case OpCode::Id::ATOMS: {
UNIMPLEMENTED_IF_MSG(instr.atoms.operation != AtomicOp::Add, "operation={}",
static_cast<int>(instr.atoms.operation.Value()));
@@ -348,7 +368,7 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
Node memory = GetSharedMemory(std::move(address));
Node data = GetRegister(instr.gpr20);
Node value = Operation(OperationCode::UAtomicAdd, std::move(memory), std::move(data));
Node value = Operation(OperationCode::AtomicAdd, std::move(memory), std::move(data));
SetRegister(bb, instr.gpr0, std::move(value));
break;
}
+102 -11
View File
@@ -10,8 +10,80 @@
namespace VideoCommon::Shader {
using std::move;
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
using Tegra::Shader::ShfType;
using Tegra::Shader::ShfXmode;
namespace {
Node IsFull(Node shift) {
return Operation(OperationCode::LogicalIEqual, move(shift), Immediate(32));
}
Node Shift(OperationCode opcode, Node value, Node shift) {
Node is_full = Operation(OperationCode::LogicalIEqual, shift, Immediate(32));
Node shifted = Operation(opcode, move(value), shift);
return Operation(OperationCode::Select, IsFull(move(shift)), Immediate(0), move(shifted));
}
Node ClampShift(Node shift, s32 size = 32) {
shift = Operation(OperationCode::IMax, move(shift), Immediate(0));
return Operation(OperationCode::IMin, move(shift), Immediate(size));
}
Node WrapShift(Node shift, s32 size = 32) {
return Operation(OperationCode::UBitwiseAnd, move(shift), Immediate(size - 1));
}
Node ShiftRight(Node low, Node high, Node shift, Node low_shift, ShfType type) {
// These values are used when the shift value is less than 32
Node less_low = Shift(OperationCode::ILogicalShiftRight, low, shift);
Node less_high = Shift(OperationCode::ILogicalShiftLeft, high, low_shift);
Node less = Operation(OperationCode::IBitwiseOr, move(less_high), move(less_low));
if (type == ShfType::Bits32) {
// On 32 bit shifts we are either full (shifting 32) or shifting less than 32 bits
return Operation(OperationCode::Select, IsFull(move(shift)), move(high), move(less));
}
// And these when it's larger than or 32
const bool is_signed = type == ShfType::S64;
const auto opcode = SignedToUnsignedCode(OperationCode::IArithmeticShiftRight, is_signed);
Node reduced = Operation(OperationCode::IAdd, shift, Immediate(-32));
Node greater = Shift(opcode, high, move(reduced));
Node is_less = Operation(OperationCode::LogicalILessThan, shift, Immediate(32));
Node is_zero = Operation(OperationCode::LogicalIEqual, move(shift), Immediate(0));
Node value = Operation(OperationCode::Select, move(is_less), move(less), move(greater));
return Operation(OperationCode::Select, move(is_zero), move(high), move(value));
}
Node ShiftLeft(Node low, Node high, Node shift, Node low_shift, ShfType type) {
// These values are used when the shift value is less than 32
Node less_low = Operation(OperationCode::ILogicalShiftRight, low, low_shift);
Node less_high = Operation(OperationCode::ILogicalShiftLeft, high, shift);
Node less = Operation(OperationCode::IBitwiseOr, move(less_low), move(less_high));
if (type == ShfType::Bits32) {
// On 32 bit shifts we are either full (shifting 32) or shifting less than 32 bits
return Operation(OperationCode::Select, IsFull(move(shift)), move(low), move(less));
}
// And these when it's larger than or 32
Node reduced = Operation(OperationCode::IAdd, shift, Immediate(-32));
Node greater = Shift(OperationCode::ILogicalShiftLeft, move(low), move(reduced));
Node is_less = Operation(OperationCode::LogicalILessThan, shift, Immediate(32));
Node is_zero = Operation(OperationCode::LogicalIEqual, move(shift), Immediate(0));
Node value = Operation(OperationCode::Select, move(is_less), move(less), move(greater));
return Operation(OperationCode::Select, move(is_zero), move(high), move(value));
}
} // Anonymous namespace
u32 ShaderIR::DecodeShift(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
@@ -28,29 +100,48 @@ u32 ShaderIR::DecodeShift(NodeBlock& bb, u32 pc) {
}
}();
switch (opcode->get().GetId()) {
switch (const auto opid = opcode->get().GetId(); opid) {
case OpCode::Id::SHR_C:
case OpCode::Id::SHR_R:
case OpCode::Id::SHR_IMM: {
if (instr.shr.wrap) {
op_b = Operation(OperationCode::UBitwiseAnd, std::move(op_b), Immediate(0x1f));
} else {
op_b = Operation(OperationCode::IMax, std::move(op_b), Immediate(0));
op_b = Operation(OperationCode::IMin, std::move(op_b), Immediate(31));
}
op_b = instr.shr.wrap ? WrapShift(move(op_b)) : ClampShift(move(op_b));
Node value = SignedOperation(OperationCode::IArithmeticShiftRight, instr.shift.is_signed,
std::move(op_a), std::move(op_b));
move(op_a), move(op_b));
SetInternalFlagsFromInteger(bb, value, instr.generates_cc);
SetRegister(bb, instr.gpr0, std::move(value));
SetRegister(bb, instr.gpr0, move(value));
break;
}
case OpCode::Id::SHL_C:
case OpCode::Id::SHL_R:
case OpCode::Id::SHL_IMM: {
const Node value = Operation(OperationCode::ILogicalShiftLeft, op_a, op_b);
Node value = Operation(OperationCode::ILogicalShiftLeft, op_a, op_b);
SetInternalFlagsFromInteger(bb, value, instr.generates_cc);
SetRegister(bb, instr.gpr0, value);
SetRegister(bb, instr.gpr0, move(value));
break;
}
case OpCode::Id::SHF_RIGHT_R:
case OpCode::Id::SHF_RIGHT_IMM:
case OpCode::Id::SHF_LEFT_R:
case OpCode::Id::SHF_LEFT_IMM: {
UNIMPLEMENTED_IF(instr.generates_cc);
UNIMPLEMENTED_IF_MSG(instr.shf.xmode != ShfXmode::None, "xmode={}",
static_cast<int>(instr.shf.xmode.Value()));
if (instr.is_b_imm) {
op_b = Immediate(static_cast<u32>(instr.shf.immediate));
}
const s32 size = instr.shf.type == ShfType::Bits32 ? 32 : 64;
Node shift = instr.shf.wrap ? WrapShift(move(op_b), size) : ClampShift(move(op_b), size);
Node negated_shift = Operation(OperationCode::INegate, shift);
Node low_shift = Operation(OperationCode::IAdd, move(negated_shift), Immediate(32));
const bool is_right = opid == OpCode::Id::SHF_RIGHT_R || opid == OpCode::Id::SHF_RIGHT_IMM;
Node value = (is_right ? ShiftRight : ShiftLeft)(
move(op_a), GetRegister(instr.gpr39), move(shift), move(low_shift), instr.shf.type);
SetRegister(bb, instr.gpr0, move(value));
break;
}
default:
+12 -5
View File
@@ -161,16 +161,16 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
case OpCode::Id::TXD: {
UNIMPLEMENTED_IF_MSG(instr.txd.UsesMiscMode(TextureMiscMode::AOFFI),
"AOFFI is not implemented");
UNIMPLEMENTED_IF_MSG(instr.txd.is_array != 0, "TXD Array is not implemented");
const bool is_array = instr.txd.is_array != 0;
u64 base_reg = instr.gpr8.Value();
const auto derivate_reg = instr.gpr20.Value();
const auto texture_type = instr.txd.texture_type.Value();
const auto coord_count = GetCoordCount(texture_type);
const Sampler* sampler = is_bindless
? GetBindlessSampler(base_reg, {{texture_type, false, false}})
: GetSampler(instr.sampler, {{texture_type, false, false}});
const Sampler* sampler =
is_bindless ? GetBindlessSampler(base_reg, {{texture_type, is_array, false}})
: GetSampler(instr.sampler, {{texture_type, is_array, false}});
Node4 values;
if (sampler == nullptr) {
for (u32 element = 0; element < values.size(); ++element) {
@@ -179,6 +179,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
WriteTexInstructionFloat(bb, instr, values);
break;
}
if (is_bindless) {
base_reg++;
}
@@ -192,8 +193,14 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
derivates.push_back(GetRegister(derivate_reg + derivate + 1));
}
Node array_node = {};
if (is_array) {
const Node info_reg = GetRegister(base_reg + coord_count);
array_node = BitfieldExtract(info_reg, 0, 16);
}
for (u32 element = 0; element < values.size(); ++element) {
MetaTexture meta{*sampler, {}, {}, {}, {}, derivates, {}, {}, {}, element};
MetaTexture meta{*sampler, array_node, {}, {}, {}, derivates, {}, {}, {}, element};
values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords);
}
+1 -1
View File
@@ -162,7 +162,7 @@ enum class OperationCode {
AtomicImageXor, /// (MetaImage, int[N] coords) -> void
AtomicImageExchange, /// (MetaImage, int[N] coords) -> void
UAtomicAdd, /// (smem, uint) -> uint
AtomicAdd, /// (memory, {u}int) -> {u}int
Branch, /// (uint branch_target) -> void
BranchIndirect, /// (uint branch_target) -> void
@@ -135,7 +135,7 @@ std::vector<CopyParams> SurfaceBaseImpl::BreakDownLayered(const SurfaceParams& i
for (u32 level = 0; level < mipmaps; level++) {
const u32 width = SurfaceParams::IntersectWidth(params, in_params, level, level);
const u32 height = SurfaceParams::IntersectHeight(params, in_params, level, level);
result.emplace_back(width, height, layer, level);
result.emplace_back(0, 0, layer, 0, 0, layer, level, level, width, height, 1);
}
}
return result;
+3 -3
View File
@@ -36,9 +36,6 @@ add_executable(yuzu
configuration/configure_filesystem.cpp
configuration/configure_filesystem.h
configuration/configure_filesystem.ui
configuration/configure_gamelist.cpp
configuration/configure_gamelist.h
configuration/configure_gamelist.ui
configuration/configure_general.cpp
configuration/configure_general.h
configuration/configure_general.ui
@@ -75,6 +72,9 @@ add_executable(yuzu
configuration/configure_touchscreen_advanced.cpp
configuration/configure_touchscreen_advanced.h
configuration/configure_touchscreen_advanced.ui
configuration/configure_ui.cpp
configuration/configure_ui.h
configuration/configure_ui.ui
configuration/configure_web.cpp
configuration/configure_web.h
configuration/configure_web.ui
+3 -3
View File
@@ -48,7 +48,7 @@
<string>General</string>
</attribute>
</widget>
<widget class="ConfigureGameList" name="gameListTab">
<widget class="ConfigureUi" name="uiTab">
<attribute name="title">
<string>Game List</string>
</attribute>
@@ -166,9 +166,9 @@
<container>1</container>
</customwidget>
<customwidget>
<class>ConfigureGameList</class>
<class>ConfigureUi</class>
<extends>QWidget</extends>
<header>configuration/configure_gamelist.h</header>
<header>configuration/configure_ui.h</header>
<container>1</container>
</customwidget>
<customwidget>
+3 -3
View File
@@ -34,7 +34,7 @@ void ConfigureDialog::SetConfiguration() {}
void ConfigureDialog::ApplyConfiguration() {
ui->generalTab->ApplyConfiguration();
ui->gameListTab->ApplyConfiguration();
ui->uiTab->ApplyConfiguration();
ui->systemTab->ApplyConfiguration();
ui->profileManagerTab->ApplyConfiguration();
ui->filesystemTab->applyConfiguration();
@@ -74,7 +74,7 @@ Q_DECLARE_METATYPE(QList<QWidget*>);
void ConfigureDialog::PopulateSelectionList() {
const std::array<std::pair<QString, QList<QWidget*>>, 5> items{
{{tr("General"), {ui->generalTab, ui->webTab, ui->debugTab, ui->gameListTab}},
{{tr("General"), {ui->generalTab, ui->webTab, ui->debugTab, ui->uiTab}},
{tr("System"), {ui->systemTab, ui->profileManagerTab, ui->serviceTab, ui->filesystemTab}},
{tr("Graphics"), {ui->graphicsTab}},
{tr("Audio"), {ui->audioTab}},
@@ -108,7 +108,7 @@ void ConfigureDialog::UpdateVisibleTabs() {
{ui->audioTab, tr("Audio")},
{ui->debugTab, tr("Debug")},
{ui->webTab, tr("Web")},
{ui->gameListTab, tr("Game List")},
{ui->uiTab, tr("UI")},
{ui->filesystemTab, tr("Filesystem")},
{ui->serviceTab, tr("Services")},
};
@@ -15,11 +15,6 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
ui->setupUi(this);
for (const auto& theme : UISettings::themes) {
ui->theme_combobox->addItem(QString::fromUtf8(theme.first),
QString::fromUtf8(theme.second));
}
SetConfiguration();
connect(ui->toggle_frame_limit, &QCheckBox::toggled, ui->frame_limit, &QSpinBox::setEnabled);
@@ -30,7 +25,6 @@ ConfigureGeneral::~ConfigureGeneral() = default;
void ConfigureGeneral::SetConfiguration() {
ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing);
ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot);
ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background);
ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit);
@@ -41,8 +35,6 @@ void ConfigureGeneral::SetConfiguration() {
void ConfigureGeneral::ApplyConfiguration() {
UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked();
UISettings::values.theme =
ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString();
UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked();
Settings::values.use_frame_limit = ui->toggle_frame_limit->isChecked();
+5 -32
View File
@@ -65,39 +65,12 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="toggle_background_pause">
<property name="text">
<string>Pause emulation when in background</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="theme_group_box">
<property name="title">
<string>Theme</string>
</property>
<layout class="QHBoxLayout" name="theme_qhbox_layout">
<item>
<layout class="QVBoxLayout" name="theme_qvbox_layout">
<item>
<layout class="QHBoxLayout" name="theme_qhbox_layout_2">
<item>
<widget class="QLabel" name="theme_label">
<property name="text">
<string>Theme:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="theme_combobox"/>
</item>
</layout>
<widget class="QCheckBox" name="toggle_background_pause">
<property name="text">
<string>Pause emulation when in background</string>
</property>
</widget>
</item>
</layout>
</item>
@@ -7,8 +7,8 @@
#include "common/common_types.h"
#include "core/settings.h"
#include "ui_configure_gamelist.h"
#include "yuzu/configuration/configure_gamelist.h"
#include "ui_configure_ui.h"
#include "yuzu/configuration/configure_ui.h"
#include "yuzu/uisettings.h"
namespace {
@@ -26,35 +26,40 @@ constexpr std::array row_text_names{
};
} // Anonymous namespace
ConfigureGameList::ConfigureGameList(QWidget* parent)
: QWidget(parent), ui(new Ui::ConfigureGameList) {
ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureUi) {
ui->setupUi(this);
for (const auto& theme : UISettings::themes) {
ui->theme_combobox->addItem(QString::fromUtf8(theme.first),
QString::fromUtf8(theme.second));
}
InitializeIconSizeComboBox();
InitializeRowComboBoxes();
SetConfiguration();
// Force game list reload if any of the relevant settings are changed.
connect(ui->show_unknown, &QCheckBox::stateChanged, this,
&ConfigureGameList::RequestGameListUpdate);
connect(ui->show_unknown, &QCheckBox::stateChanged, this, &ConfigureUi::RequestGameListUpdate);
connect(ui->icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&ConfigureGameList::RequestGameListUpdate);
&ConfigureUi::RequestGameListUpdate);
connect(ui->row_1_text_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&ConfigureGameList::RequestGameListUpdate);
&ConfigureUi::RequestGameListUpdate);
connect(ui->row_2_text_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&ConfigureGameList::RequestGameListUpdate);
&ConfigureUi::RequestGameListUpdate);
// Update text ComboBoxes after user interaction.
connect(ui->row_1_text_combobox, QOverload<int>::of(&QComboBox::activated),
[=]() { ConfigureGameList::UpdateSecondRowComboBox(); });
[=]() { ConfigureUi::UpdateSecondRowComboBox(); });
connect(ui->row_2_text_combobox, QOverload<int>::of(&QComboBox::activated),
[=]() { ConfigureGameList::UpdateFirstRowComboBox(); });
[=]() { ConfigureUi::UpdateFirstRowComboBox(); });
}
ConfigureGameList::~ConfigureGameList() = default;
ConfigureUi::~ConfigureUi() = default;
void ConfigureGameList::ApplyConfiguration() {
void ConfigureUi::ApplyConfiguration() {
UISettings::values.theme =
ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString();
UISettings::values.show_unknown = ui->show_unknown->isChecked();
UISettings::values.show_add_ons = ui->show_add_ons->isChecked();
UISettings::values.icon_size = ui->icon_size_combobox->currentData().toUInt();
@@ -63,18 +68,19 @@ void ConfigureGameList::ApplyConfiguration() {
Settings::Apply();
}
void ConfigureGameList::RequestGameListUpdate() {
void ConfigureUi::RequestGameListUpdate() {
UISettings::values.is_game_list_reload_pending.exchange(true);
}
void ConfigureGameList::SetConfiguration() {
void ConfigureUi::SetConfiguration() {
ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
ui->show_unknown->setChecked(UISettings::values.show_unknown);
ui->show_add_ons->setChecked(UISettings::values.show_add_ons);
ui->icon_size_combobox->setCurrentIndex(
ui->icon_size_combobox->findData(UISettings::values.icon_size));
}
void ConfigureGameList::changeEvent(QEvent* event) {
void ConfigureUi::changeEvent(QEvent* event) {
if (event->type() == QEvent::LanguageChange) {
RetranslateUI();
}
@@ -82,7 +88,7 @@ void ConfigureGameList::changeEvent(QEvent* event) {
QWidget::changeEvent(event);
}
void ConfigureGameList::RetranslateUI() {
void ConfigureUi::RetranslateUI() {
ui->retranslateUi(this);
for (int i = 0; i < ui->icon_size_combobox->count(); i++) {
@@ -97,18 +103,18 @@ void ConfigureGameList::RetranslateUI() {
}
}
void ConfigureGameList::InitializeIconSizeComboBox() {
void ConfigureUi::InitializeIconSizeComboBox() {
for (const auto& size : default_icon_sizes) {
ui->icon_size_combobox->addItem(QString::fromUtf8(size.second), size.first);
}
}
void ConfigureGameList::InitializeRowComboBoxes() {
void ConfigureUi::InitializeRowComboBoxes() {
UpdateFirstRowComboBox(true);
UpdateSecondRowComboBox(true);
}
void ConfigureGameList::UpdateFirstRowComboBox(bool init) {
void ConfigureUi::UpdateFirstRowComboBox(bool init) {
const int currentIndex =
init ? UISettings::values.row_1_text_id
: ui->row_1_text_combobox->findData(ui->row_1_text_combobox->currentData());
@@ -127,7 +133,7 @@ void ConfigureGameList::UpdateFirstRowComboBox(bool init) {
ui->row_1_text_combobox->findData(ui->row_2_text_combobox->currentData()));
}
void ConfigureGameList::UpdateSecondRowComboBox(bool init) {
void ConfigureUi::UpdateSecondRowComboBox(bool init) {
const int currentIndex =
init ? UISettings::values.row_2_text_id
: ui->row_2_text_combobox->findData(ui->row_2_text_combobox->currentData());
@@ -8,15 +8,15 @@
#include <QWidget>
namespace Ui {
class ConfigureGameList;
class ConfigureUi;
}
class ConfigureGameList : public QWidget {
class ConfigureUi : public QWidget {
Q_OBJECT
public:
explicit ConfigureGameList(QWidget* parent = nullptr);
~ConfigureGameList() override;
explicit ConfigureUi(QWidget* parent = nullptr);
~ConfigureUi() override;
void ApplyConfiguration();
@@ -34,5 +34,5 @@ private:
void UpdateFirstRowComboBox(bool init = false);
void UpdateSecondRowComboBox(bool init = false);
std::unique_ptr<Ui::ConfigureGameList> ui;
std::unique_ptr<Ui::ConfigureUi> ui;
};
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigureGameList</class>
<widget class="QWidget" name="ConfigureGameList">
<class>ConfigureUi</class>
<widget class="QWidget" name="ConfigureUi">
<property name="geometry">
<rect>
<x>0</x>
@@ -21,7 +21,34 @@
<property name="title">
<string>General</string>
</property>
<layout class="QHBoxLayout" name="GeneralHorizontalLayout">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="theme_label">
<property name="text">
<string>Theme:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="theme_combobox"/>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="GameListGroupBox">
<property name="title">
<string>Game List</string>
</property>
<layout class="QHBoxLayout" name="GameListHorizontalLayout">
<item>
<layout class="QVBoxLayout" name="GeneralVerticalLayout">
<item>
@@ -38,19 +65,6 @@
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="IconSizeGroupBox">
<property name="title">
<string>Icon Size</string>
</property>
<layout class="QHBoxLayout" name="icon_size_qhbox_layout">
<item>
<layout class="QVBoxLayout" name="icon_size_qvbox_layout">
<item>
<layout class="QHBoxLayout" name="icon_size_qhbox_layout_2">
<item>
@@ -65,19 +79,6 @@
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="RowGroupBox">
<property name="title">
<string>Row Text</string>
</property>
<layout class="QHBoxLayout" name="RowHorizontalLayout">
<item>
<layout class="QVBoxLayout" name="RowVerticalLayout">
<item>
<layout class="QHBoxLayout" name="row_1_qhbox_layout">
<item>