Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2de2bb980e | |||
| 16e7b7b83d | |||
| 51927bc9dc | |||
| 985d0f35e5 | |||
| 8a7cdfc3ff | |||
| c593e45dbd | |||
| 2db7adc42a | |||
| b11aeced18 | |||
| 91f79225e7 | |||
| c457e47297 | |||
| 8178fe8960 | |||
| 283f3253bc | |||
| bea6327d74 | |||
| abae795986 | |||
| acfb0b4852 | |||
| f55f6ff9bb | |||
| d17dfa6104 | |||
| f68bb4f55e | |||
| d95d4ac843 | |||
| d26e74f0a3 | |||
| 9a2cdf8520 | |||
| 531f25a037 | |||
| 96638f57c9 | |||
| 2a822f3378 | |||
| 05df4a8c94 | |||
| 2b1d66eda3 | |||
| 845a5dbca9 | |||
| dfd998216c | |||
| a104b985a8 | |||
| f64adcfc37 | |||
| 1690f1adba | |||
| d0e4f1c6f4 | |||
| a31ed02ae4 | |||
| 5a7eecc3ad | |||
| 4e9331f45d | |||
| 999e3f89b9 | |||
| a1667a7b46 |
Vendored
+112
-110
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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__)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2,14 +2,12 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_manager.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/cpu_manager.h"
|
||||
#include "core/gdbstub/gdbstub.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,6 @@
|
||||
|
||||
namespace FileSys::SystemArchive::SharedFontData {
|
||||
|
||||
extern const std::array<unsigned char, 217276> FONT_CHINESE_SIMPLIFIED;
|
||||
extern const std::array<unsigned char, 8334256> FONT_CHINESE_SIMPLIFIED;
|
||||
|
||||
} // namespace FileSys::SystemArchive::SharedFontData
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
namespace FileSys::SystemArchive::SharedFontData {
|
||||
|
||||
// clang-format off
|
||||
const std::array<unsigned char, 293516> FONT_EXTENDED_CHINESE_SIMPLIFIED{{
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x04, 0x00, 0x30, 0x42, 0x41, 0x53, 0x45,
|
||||
0x65, 0x1e, 0x5d, 0xbd, 0x00, 0x03, 0x1e, 0xf4, 0x00, 0x00, 0x00, 0x46, 0x44, 0x53, 0x49, 0x47,
|
||||
@@ -18353,5 +18354,6 @@ const std::array<unsigned char, 293516> FONT_EXTENDED_CHINESE_SIMPLIFIED{{
|
||||
0xbf, 0x6c, 0x52, 0x24, 0x3e, 0xb4, 0xc6, 0x1e, 0xe1, 0x7d, 0xdf, 0x7a, 0x97, 0xeb, 0xb4, 0xe2,
|
||||
0xda, 0x7e, 0x74, 0xf9, 0x01, 0xc4, 0xbc, 0x7e, 0xf9, 0x00, 0x00, 0x00,
|
||||
}};
|
||||
// clang-format on
|
||||
|
||||
} // namespace FileSys::SystemArchive::SharedFontData
|
||||
|
||||
+185638
-13581
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,6 @@
|
||||
|
||||
namespace FileSys::SystemArchive::SharedFontData {
|
||||
|
||||
extern const std::array<unsigned char, 217276> FONT_KOREAN;
|
||||
extern const std::array<unsigned char, 2227620> FONT_KOREAN;
|
||||
|
||||
} // namespace FileSys::SystemArchive::SharedFontData
|
||||
|
||||
@@ -101,7 +101,7 @@ struct KernelCore::Impl {
|
||||
void Initialize(KernelCore& kernel) {
|
||||
Shutdown();
|
||||
|
||||
InitializePhysicalCores(kernel);
|
||||
InitializePhysicalCores();
|
||||
InitializeSystemResourceLimit(kernel);
|
||||
InitializeThreads();
|
||||
InitializePreemption();
|
||||
@@ -131,14 +131,14 @@ struct KernelCore::Impl {
|
||||
}
|
||||
cores.clear();
|
||||
|
||||
exclusive_monitor.reset(nullptr);
|
||||
exclusive_monitor.reset();
|
||||
}
|
||||
|
||||
void InitializePhysicalCores(KernelCore& kernel) {
|
||||
void InitializePhysicalCores() {
|
||||
exclusive_monitor =
|
||||
Core::MakeExclusiveMonitor(system.Memory(), global_scheduler.CpuCoresCount());
|
||||
for (std::size_t i = 0; i < global_scheduler.CpuCoresCount(); i++) {
|
||||
cores.emplace_back(system, kernel, i, *exclusive_monitor);
|
||||
cores.emplace_back(system, i, *exclusive_monitor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,24 +10,23 @@
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/arm/unicorn/arm_unicorn.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/physical_core.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
PhysicalCore::PhysicalCore(Core::System& system, KernelCore& kernel, std::size_t id,
|
||||
PhysicalCore::PhysicalCore(Core::System& system, std::size_t id,
|
||||
Core::ExclusiveMonitor& exclusive_monitor)
|
||||
: core_index{id}, kernel{kernel} {
|
||||
: core_index{id} {
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
arm_interface = std::make_shared<Core::ARM_Dynarmic>(system, exclusive_monitor, core_index);
|
||||
arm_interface = std::make_unique<Core::ARM_Dynarmic>(system, exclusive_monitor, core_index);
|
||||
#else
|
||||
arm_interface = std::make_shared<Core::ARM_Unicorn>(system);
|
||||
LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
|
||||
#endif
|
||||
|
||||
scheduler = std::make_shared<Kernel::Scheduler>(system, *arm_interface, core_index);
|
||||
scheduler = std::make_unique<Kernel::Scheduler>(system, *arm_interface, core_index);
|
||||
}
|
||||
|
||||
PhysicalCore::~PhysicalCore() = default;
|
||||
|
||||
@@ -21,11 +21,15 @@ namespace Kernel {
|
||||
|
||||
class PhysicalCore {
|
||||
public:
|
||||
PhysicalCore(Core::System& system, KernelCore& kernel, std::size_t id,
|
||||
Core::ExclusiveMonitor& exclusive_monitor);
|
||||
|
||||
PhysicalCore(Core::System& system, std::size_t id, Core::ExclusiveMonitor& exclusive_monitor);
|
||||
~PhysicalCore();
|
||||
|
||||
PhysicalCore(const PhysicalCore&) = delete;
|
||||
PhysicalCore& operator=(const PhysicalCore&) = delete;
|
||||
|
||||
PhysicalCore(PhysicalCore&&) = default;
|
||||
PhysicalCore& operator=(PhysicalCore&&) = default;
|
||||
|
||||
/// Execute current jit state
|
||||
void Run();
|
||||
/// Execute a single instruction in current jit.
|
||||
@@ -66,9 +70,8 @@ public:
|
||||
|
||||
private:
|
||||
std::size_t core_index;
|
||||
KernelCore& kernel;
|
||||
std::shared_ptr<Core::ARM_Interface> arm_interface;
|
||||
std::shared_ptr<Kernel::Scheduler> scheduler;
|
||||
std::unique_ptr<Core::ARM_Interface> arm_interface;
|
||||
std::unique_ptr<Kernel::Scheduler> scheduler;
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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()), {}};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
@@ -957,6 +979,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 +1718,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 +2023,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>);
|
||||
|
||||
@@ -19,9 +19,12 @@ 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;
|
||||
using Tegra::Shader::StoreType;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -61,6 +64,27 @@ u32 GetMemorySize(Tegra::Shader::UniformType uniform_type) {
|
||||
}
|
||||
}
|
||||
|
||||
Node ExtractUnaligned(Node value, Node address, u32 mask, u32 size) {
|
||||
Node offset = Operation(OperationCode::UBitwiseAnd, address, Immediate(mask));
|
||||
offset = Operation(OperationCode::ULogicalShiftLeft, std::move(offset), Immediate(3));
|
||||
return Operation(OperationCode::UBitfieldExtract, std::move(value), std::move(offset),
|
||||
Immediate(size));
|
||||
}
|
||||
|
||||
Node InsertUnaligned(Node dest, Node value, Node address, u32 mask, u32 size) {
|
||||
Node offset = Operation(OperationCode::UBitwiseAnd, std::move(address), Immediate(mask));
|
||||
offset = Operation(OperationCode::ULogicalShiftLeft, std::move(offset), Immediate(3));
|
||||
return Operation(OperationCode::UBitfieldInsert, std::move(dest), std::move(value),
|
||||
std::move(offset), Immediate(size));
|
||||
}
|
||||
|
||||
Node Sign16Extend(Node value) {
|
||||
Node sign = Operation(OperationCode::UBitwiseAnd, value, Immediate(1U << 15));
|
||||
Node is_sign = Operation(OperationCode::LogicalUEqual, std::move(sign), Immediate(1U << 15));
|
||||
Node extend = Operation(OperationCode::Select, is_sign, Immediate(0xFFFF0000), Immediate(0));
|
||||
return Operation(OperationCode::UBitwiseOr, std::move(value), std::move(extend));
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
|
||||
@@ -136,26 +160,31 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
|
||||
LOG_DEBUG(HW_GPU, "LD_L cache management mode: {}", static_cast<u64>(instr.ld_l.unknown));
|
||||
[[fallthrough]];
|
||||
case OpCode::Id::LD_S: {
|
||||
const auto GetMemory = [&](s32 offset) {
|
||||
const auto GetAddress = [&](s32 offset) {
|
||||
ASSERT(offset % 4 == 0);
|
||||
const Node immediate_offset = Immediate(static_cast<s32>(instr.smem_imm) + offset);
|
||||
const Node address = Operation(OperationCode::IAdd, NO_PRECISE, GetRegister(instr.gpr8),
|
||||
immediate_offset);
|
||||
return opcode->get().GetId() == OpCode::Id::LD_S ? GetSharedMemory(address)
|
||||
: GetLocalMemory(address);
|
||||
return Operation(OperationCode::IAdd, GetRegister(instr.gpr8), immediate_offset);
|
||||
};
|
||||
const auto GetMemory = [&](s32 offset) {
|
||||
return opcode->get().GetId() == OpCode::Id::LD_S ? GetSharedMemory(GetAddress(offset))
|
||||
: GetLocalMemory(GetAddress(offset));
|
||||
};
|
||||
|
||||
switch (instr.ldst_sl.type.Value()) {
|
||||
case Tegra::Shader::StoreType::Bits32:
|
||||
case Tegra::Shader::StoreType::Bits64:
|
||||
case Tegra::Shader::StoreType::Bits128: {
|
||||
const u32 count = [&]() {
|
||||
case StoreType::Signed16:
|
||||
SetRegister(bb, instr.gpr0,
|
||||
Sign16Extend(ExtractUnaligned(GetMemory(0), GetAddress(0), 0b10, 16)));
|
||||
break;
|
||||
case StoreType::Bits32:
|
||||
case StoreType::Bits64:
|
||||
case StoreType::Bits128: {
|
||||
const u32 count = [&] {
|
||||
switch (instr.ldst_sl.type.Value()) {
|
||||
case Tegra::Shader::StoreType::Bits32:
|
||||
case StoreType::Bits32:
|
||||
return 1;
|
||||
case Tegra::Shader::StoreType::Bits64:
|
||||
case StoreType::Bits64:
|
||||
return 2;
|
||||
case Tegra::Shader::StoreType::Bits128:
|
||||
case StoreType::Bits128:
|
||||
return 4;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@@ -212,12 +241,7 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
|
||||
// To handle unaligned loads get the bytes used to dereference global memory and extract
|
||||
// those bytes from the loaded u32.
|
||||
if (IsUnaligned(type)) {
|
||||
Node mask = Immediate(GetUnalignedMask(type));
|
||||
Node offset = Operation(OperationCode::UBitwiseAnd, real_address, std::move(mask));
|
||||
offset = Operation(OperationCode::ULogicalShiftLeft, offset, Immediate(3));
|
||||
|
||||
gmem = Operation(OperationCode::UBitfieldExtract, std::move(gmem),
|
||||
std::move(offset), Immediate(size));
|
||||
gmem = ExtractUnaligned(gmem, real_address, GetUnalignedMask(type), size);
|
||||
}
|
||||
|
||||
SetTemporary(bb, i, gmem);
|
||||
@@ -269,21 +293,28 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
|
||||
return Operation(OperationCode::IAdd, NO_PRECISE, GetRegister(instr.gpr8), immediate);
|
||||
};
|
||||
|
||||
const auto set_memory = opcode->get().GetId() == OpCode::Id::ST_L
|
||||
? &ShaderIR::SetLocalMemory
|
||||
: &ShaderIR::SetSharedMemory;
|
||||
const bool is_local = opcode->get().GetId() == OpCode::Id::ST_L;
|
||||
const auto set_memory = is_local ? &ShaderIR::SetLocalMemory : &ShaderIR::SetSharedMemory;
|
||||
const auto get_memory = is_local ? &ShaderIR::GetLocalMemory : &ShaderIR::GetSharedMemory;
|
||||
|
||||
switch (instr.ldst_sl.type.Value()) {
|
||||
case Tegra::Shader::StoreType::Bits128:
|
||||
case StoreType::Bits128:
|
||||
(this->*set_memory)(bb, GetAddress(12), GetRegister(instr.gpr0.Value() + 3));
|
||||
(this->*set_memory)(bb, GetAddress(8), GetRegister(instr.gpr0.Value() + 2));
|
||||
[[fallthrough]];
|
||||
case Tegra::Shader::StoreType::Bits64:
|
||||
case StoreType::Bits64:
|
||||
(this->*set_memory)(bb, GetAddress(4), GetRegister(instr.gpr0.Value() + 1));
|
||||
[[fallthrough]];
|
||||
case Tegra::Shader::StoreType::Bits32:
|
||||
case StoreType::Bits32:
|
||||
(this->*set_memory)(bb, GetAddress(0), GetRegister(instr.gpr0));
|
||||
break;
|
||||
case StoreType::Signed16: {
|
||||
Node address = GetAddress(0);
|
||||
Node memory = (this->*get_memory)(address);
|
||||
(this->*set_memory)(
|
||||
bb, address, InsertUnaligned(memory, GetRegister(instr.gpr0), address, 0b10, 16));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("{} unhandled type: {}", opcode->get().GetName(),
|
||||
static_cast<u32>(instr.ldst_sl.type.Value()));
|
||||
@@ -323,18 +354,32 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
|
||||
Node value = GetRegister(instr.gpr0.Value() + i);
|
||||
|
||||
if (IsUnaligned(type)) {
|
||||
Node mask = Immediate(GetUnalignedMask(type));
|
||||
Node offset = Operation(OperationCode::UBitwiseAnd, real_address, std::move(mask));
|
||||
offset = Operation(OperationCode::ULogicalShiftLeft, offset, Immediate(3));
|
||||
|
||||
value = Operation(OperationCode::UBitfieldInsert, gmem, std::move(value), offset,
|
||||
Immediate(size));
|
||||
const u32 mask = GetUnalignedMask(type);
|
||||
value = InsertUnaligned(gmem, std::move(value), real_address, mask, size);
|
||||
}
|
||||
|
||||
bb.push_back(Operation(OperationCode::Assign, gmem, value));
|
||||
}
|
||||
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 +393,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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
|
||||
+27
-21
@@ -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;
|
||||
};
|
||||
+30
-29
@@ -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>
|
||||
Reference in New Issue
Block a user