mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4bc3ab6285 | ||
|
|
1adc9cbb49 | ||
|
|
7cdf5eefc9 | ||
|
|
c7ee72647d | ||
|
|
5434af348e | ||
|
|
169cea0f01 | ||
|
|
a8f3ec8184 | ||
|
|
7796b2a12b | ||
|
|
d9cffd58ba | ||
|
|
e566386240 | ||
|
|
45af1e172f | ||
|
|
768b2e52a6 | ||
|
|
7abd2009b0 | ||
|
|
46f075e891 | ||
|
|
832c381ac4 | ||
|
|
e021282264 | ||
|
|
2a60d385c6 | ||
|
|
4d37e35675 | ||
|
|
df3868a280 | ||
|
|
0799bb8cf1 | ||
|
|
69048dede4 | ||
|
|
76df6d1f43 |
54
.github/CONTRIBUTING.md
vendored
54
.github/CONTRIBUTING.md
vendored
@@ -1,54 +0,0 @@
|
||||
# So you want to contribute to PCSX2? Great
|
||||
|
||||
As a first step, please review these links as they'll help you understand how the development of PCSX2 works.
|
||||
|
||||
* [Just Starting Out](#just-starting-out)
|
||||
* [Issue Reporting](#issue-reporting)
|
||||
* [Pull Request Guidelines](#pull-request-guidelines)
|
||||
* [General Documentation And Coding Strategies](#general-documentation-and-coding-strategies)
|
||||
* [Tasks](#tasks)
|
||||
|
||||
## Just Starting Out
|
||||
|
||||
* If you're unfamilar with git, check out this [brief introduction to Git](https://github.com/PCSX2/pcsx2/wiki/07-Git-survival-guide)
|
||||
* [How to build PCSX2 for Windows](https://github.com/PCSX2/pcsx2/wiki/12-Building-on-Windows)
|
||||
* [How to build PCSX2 for Linux](https://github.com/PCSX2/pcsx2/wiki/10-Building-on-Linux)
|
||||
|
||||
## Issue Reporting
|
||||
|
||||
* [How to write a useful issue](https://github.com/PCSX2/pcsx2/wiki/How-to-create-useful-and-valid-issues)
|
||||
|
||||
## Pull Request Guidelines
|
||||
|
||||
The following is a list of *general* style recommendations that will make reviewing and merging easier:
|
||||
|
||||
* Commit Messages
|
||||
* Please try to prefix your commit message, indicating what area of the project was modified.
|
||||
* For example `gs: message...`.
|
||||
* Looking at the project's commit history will help with keeping prefixes consistent overtime, *there is no strictly enforced list*.
|
||||
|
||||
* Try to keep messages brief and informative
|
||||
|
||||
* Remove unnecessary commits and squash commits together when appropriate.
|
||||
* If you are not familiar with rebasing with git, check out the following resources:
|
||||
* CLI - https://thoughtbot.com/blog/git-interactive-rebase-squash-amend-rewriting-history
|
||||
* GUI (SourceTree) - https://www.atlassian.com/blog/sourcetree/interactive-rebase-sourcetree
|
||||
|
||||
* Code Styling and Formatting
|
||||
* [Consult the style guide](https://github.com/tadanokojin/pcsx2/blob/coding-guide/pcsx2/Docs/Coding_Guidelines.md)
|
||||
|
||||
* Run `clang-format` using the configuration file in the root of the repository
|
||||
* Visual Studio Setup - https://devblogs.microsoft.com/cppblog/clangformat-support-in-visual-studio-2017-15-7-preview-1/
|
||||
* IMPORTANT - if you are running `clang-format` on unrelated changes (ie. formatting an entire file), please do so in a separate commit.
|
||||
* If you cannot scope your `clang-format` to just your changes and do not want to format unrelated code. Try your best to stick with the existing formatting already established in the file in question.
|
||||
|
||||
## General Documentation And Coding Strategies
|
||||
|
||||
* [Commenting Etiquette](https://github.com/PCSX2/pcsx2/wiki/06-Commenting-Etiquette)
|
||||
|
||||
* [Coding style](https://github.com/PCSX2/pcsx2/wiki/Code-Formatting-Guidelines)
|
||||
* [More comprehensive style-guide (Currently in Draft)](https://github.com/tadanokojin/pcsx2/blob/coding-guide/pcsx2/Docs/Coding_Guidelines.md)
|
||||
|
||||
## Tasks
|
||||
|
||||
* [Issues](https://github.com/PCSX2/pcsx2/issues)
|
||||
4
.github/ISSUE_TEMPLATE/emu_bug_report.yaml
vendored
4
.github/ISSUE_TEMPLATE/emu_bug_report.yaml
vendored
@@ -66,6 +66,10 @@ body:
|
||||
|
||||
Performance issues as a result of not meeting our hardware requirements are not valid.
|
||||
|
||||
Please read our troubleshooting pages and our issue reporting guide.
|
||||
- [Troubleshooting page](https://pcsx2.net/docs/category/troubleshooting).
|
||||
- [Issue reporting guide](https://pcsx2.net/docs/troubleshooting/identify).
|
||||
|
||||
We are **not** accepting issues related to the **libretro** core. The libretro core is being maintained separately at this time
|
||||
- type: input
|
||||
id: rev
|
||||
|
||||
@@ -11,7 +11,7 @@ merge_binaries() {
|
||||
"
|
||||
pushd "$X86DIR"
|
||||
for X86BIN in $(find . -type f \( -name '*.dylib' -o -name '*.a' -o -perm +111 \)); do
|
||||
if file "$X86DIR/$X86BIN" | grep "Mach-O " >/dev/null; then
|
||||
if file "$X86DIR/$X86BIN" | grep "Mach-O.*x86_64" >/dev/null; then
|
||||
ARMBIN="${ARMDIR}/${X86BIN}"
|
||||
echo "Merge $ARMBIN to $X86BIN..."
|
||||
lipo -create "$X86BIN" "$ARMBIN" -o "$X86BIN"
|
||||
@@ -112,11 +112,11 @@ curl -C - -L \
|
||||
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
|
||||
-O "https://ffmpeg.org/releases/ffmpeg-$FFMPEG.tar.xz" \
|
||||
-O "https://github.com/KhronosGroup/MoltenVK/archive/refs/tags/v$MOLTENVK.tar.gz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
-o "shaderc-$SHADERC.tar.gz" "https://github.com/google/shaderc/archive/refs/tags/v$SHADERC.tar.gz" \
|
||||
-o "shaderc-glslang-$SHADERC_GLSLANG.tar.gz" "https://github.com/KhronosGroup/glslang/archive/$SHADERC_GLSLANG.tar.gz" \
|
||||
-o "shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Headers/archive/$SHADERC_SPIRVHEADERS.tar.gz" \
|
||||
@@ -213,8 +213,11 @@ echo "Installing libjpegturbo..."
|
||||
rm -fr "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
tar xf "libjpeg-turbo-$LIBJPEGTURBO.tar.gz"
|
||||
cd "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_ARM64" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build-arm64
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_X64" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build
|
||||
make -C build "-j$NPROCS"
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_ARM64" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build-arm64
|
||||
make -C build-arm64 "-j$NPROCS"
|
||||
merge_binaries $(realpath build) $(realpath build-arm64)
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
@@ -380,7 +383,7 @@ echo "Building PlutoVG..."
|
||||
rm -fr "plutovg-$PLUTOVG"
|
||||
tar xf "plutovg-$PLUTOVG.tar.gz"
|
||||
cd "plutovg-$PLUTOVG"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DPLUTOVG_BUILD_EXAMPLES=OFF -B build
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DBUILD_SHARED_LIBS=ON -DPLUTOVG_BUILD_EXAMPLES=OFF -B build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
@@ -389,7 +392,7 @@ echo "Building PlutoSVG..."
|
||||
rm -fr "plutosvg-$PLUTOSVG"
|
||||
tar xf "plutosvg-$PLUTOSVG.tar.gz"
|
||||
cd "plutosvg-$PLUTOSVG"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=ON -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=ON -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
@@ -66,7 +66,7 @@ const embed = new MessageEmbed()
|
||||
.setDescription("To download the latest or previous builds, [visit the official downloads page](https://pcsx2.net/downloads/).")
|
||||
.addFields(
|
||||
{ name: 'Version', value: releaseInfo.tag_name, inline: true },
|
||||
{ name: 'Installation Steps', value: '[See Here](https://github.com/PCSX2/pcsx2/wiki/Nightly-Build-Usage-Guide)', inline: true },
|
||||
{ name: 'Installation Steps', value: '[See Here](https://pcsx2.net/docs/category/setup)', inline: true },
|
||||
{ name: 'Included Changes', value: releaseInfo.body, inline: false }
|
||||
);
|
||||
console.log(embed);
|
||||
|
||||
@@ -24,4 +24,4 @@ Please note that a BIOS dump from a legitimately-owned PS2 console is required t
|
||||
|
||||
PCSX2 supports translation into other languages using [Crowdin](https://crowdin.com/project/pcsx2-emulator).
|
||||
|
||||
See the [Contributing Guidelines](https://github.com/PCSX2/pcsx2/blob/master/.github/CONTRIBUTING.md) or visit the [GitHub Wiki](https://github.com/PCSX2/pcsx2/wiki) for more info on how to contribute.
|
||||
See the [Contribution Guide](https://pcsx2.net/docs/contributing/) for more info on how to contribute.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1100,6 +1100,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X,
|
||||
050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X,
|
||||
030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4~,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000006f0e00000104000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000c6240000045d000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
@@ -1766,6 +1767,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
050000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000fd02000030110000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000dd02000003020000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000005e040000e302000002090000,Xbox One Elite,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
|
||||
@@ -65,16 +65,17 @@ void ThreadView::openContextMenu(QPoint pos)
|
||||
|
||||
void ThreadView::onDoubleClick(const QModelIndex& index)
|
||||
{
|
||||
auto real_index = m_proxy_model->mapToSource(index);
|
||||
switch (index.column())
|
||||
{
|
||||
case ThreadModel::ThreadColumns::ENTRY:
|
||||
{
|
||||
goToInMemoryView(m_model->data(index, Qt::UserRole).toUInt(), true);
|
||||
goToInDisassembler(m_model->data(real_index, Qt::UserRole).toUInt(), true);
|
||||
break;
|
||||
}
|
||||
default: // Default to PC
|
||||
{
|
||||
QModelIndex pc_index = m_model->index(index.row(), ThreadModel::ThreadColumns::PC);
|
||||
QModelIndex pc_index = m_model->index(real_index.row(), ThreadModel::ThreadColumns::PC);
|
||||
goToInDisassembler(m_model->data(pc_index, Qt::UserRole).toUInt(), true);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ struct BreakPoint
|
||||
bool temporary = false;
|
||||
bool stepping = false;
|
||||
|
||||
bool hasCond;
|
||||
bool hasCond = false;
|
||||
BreakPointCond cond;
|
||||
BreakPointCpu cpu;
|
||||
|
||||
|
||||
@@ -20,7 +20,11 @@ There are a number of ways to help the project, whether it be bug reporting, gam
|
||||
|
||||
* Want to make changes to emulator code? [Check out the issue tracker](https://github.com/PCSX2/pcsx2/issues), or [fork the PCSX2 repository and work on your own ideas](https://github.com/PCSX2/pcsx2).
|
||||
* Want to patch games? [Check out the cheats and patches forum thread for inspiration](https://forums.pcsx2.net/Thread-Post-your-PCSX2-cheats-patches-here). There are other threads to find as well, [such as those dedicated to 60 FPS patches](https://forums.pcsx2.net/Thread-60-fps-codes) or [widescreen patches](https://forums.pcsx2.net/Thread-PCSX2-Widescreen-Game-Patches).
|
||||
<<<<<<< HEAD
|
||||
* Want to report bugs you have discovered in your games? Head over to [the Bug Reporting section of the PCSX2 forums](https://forums.pcsx2.net/Forum-Bug-reporting), to [the PCSX2 Discord](https://pcsx2.net/discord), or to [the GitHub issues section](https://github.com/PCSX2/pcsx2/issues).
|
||||
=======
|
||||
* Want to report bugs you have discovered in your games? [Head over to the Bug Reporting section of the PCSX2 forums](https://forums.pcsx2.net/Forum-Bug-reporting). Also check out our [Issue reporting guide](https://pcsx2.net/docs/troubleshooting/identify) for info on how to better report to us issues.
|
||||
>>>>>>> 091a4ee5a (docs: update in order to redirect from the GH wiki to our website)
|
||||
* Want to update us on the compatibility of your games? [Take a look at the Public Compatibility List on the PCSX2 forums](https://forums.pcsx2.net/Forum-Public-compatibility-list)
|
||||
* Want to improve the PCSX2 wiki? [Here is how to contribute](https://wiki.pcsx2.net/How_to_contribute)
|
||||
|
||||
@@ -120,9 +124,7 @@ If you are using a disc:
|
||||
Fast Boot, enabled by default, will directly mount and launch the game without first launching the PS2 BIOS. You may disable this in Settings > BIOS > Fast Boot if you wish to see the BIOS startup animation or if Fast Boot is causing an issue.
|
||||
|
||||
### Question 18: How do I build the PCSX2 source code?
|
||||
* [Windows build guide](https://github.com/PCSX2/pcsx2/wiki/12-Building-on-Windows)
|
||||
* [Linux build guide](https://github.com/PCSX2/pcsx2/wiki/10-Building-on-Linux)
|
||||
* [macOS build guide](https://github.com/PCSX2/pcsx2/wiki/11-Building-on-MacOS)
|
||||
Have a nice [building guide](https://pcsx2.net/docs/advanced/building) :) .
|
||||
|
||||
### Question 19: When will the next version be released?
|
||||
It will be released when it is ready. Please don't waste your time and ours asking when.
|
||||
|
||||
@@ -462,7 +462,8 @@ void GSClut::GetAlphaMinMax32(int& amin_out, int& amax_out)
|
||||
{
|
||||
// call only after Read32
|
||||
|
||||
pxAssert(!m_read.dirty);
|
||||
if (m_read.dirty)
|
||||
GL_INS("GSClut: GetAlphaMinMax32 m_read.dirty");
|
||||
|
||||
if (m_read.adirty)
|
||||
{
|
||||
|
||||
@@ -1236,36 +1236,18 @@ void GSDevice11::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r,
|
||||
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
|
||||
D3D11_BOX box = {(UINT)r.left, (UINT)r.top, 0U, (UINT)r.right, (UINT)r.bottom, 1U};
|
||||
D3D11_BOX box = {static_cast<UINT>(r.left), static_cast<UINT>(r.top), 0U, static_cast<UINT>(r.right), static_cast<UINT>(r.bottom), 1U};
|
||||
|
||||
// DX api isn't happy if we pass a box for depth copy
|
||||
// It complains that depth/multisample must be a full copy
|
||||
// and asks us to use a NULL for the box
|
||||
// DX11 doesn't support partial depth copy so we need to
|
||||
// either pass a nullptr D3D11_BOX for a full depth copy or use CopyResource instead.
|
||||
// Alternatively use shader copy StretchRect, or full depth copy with
|
||||
// adjusting the scissor and UVs in the shader.
|
||||
const bool depth = (sTex->GetType() == GSTexture::Type::DepthStencil);
|
||||
auto pBox = depth ? nullptr : &box;
|
||||
const u32 x = depth ? 0 : destX;
|
||||
const u32 y = depth ? 0 : destY;
|
||||
|
||||
m_ctx->CopySubresourceRegion(*(GSTexture11*)dTex, 0, destX, destY, 0, *(GSTexture11*)sTex, 0, pBox);
|
||||
}
|
||||
|
||||
void GSDevice11::CloneTexture(GSTexture* src, GSTexture** dest, const GSVector4i& rect)
|
||||
{
|
||||
pxAssertMsg(src->GetType() == GSTexture::Type::DepthStencil || src->GetType() == GSTexture::Type::RenderTarget, "Source is RT or DS.");
|
||||
CommitClear(src);
|
||||
|
||||
const int w = src->GetWidth();
|
||||
const int h = src->GetHeight();
|
||||
|
||||
if (src->GetType() == GSTexture::Type::DepthStencil)
|
||||
{
|
||||
// DX11 requires that you copy the entire depth buffer.
|
||||
*dest = CreateDepthStencil(w, h, src->GetFormat(), false);
|
||||
CopyRect(src, *dest, GSVector4i(0, 0, w, h), 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
*dest = CreateRenderTarget(w, h, src->GetFormat(), false);
|
||||
CopyRect(src, *dest, rect, rect.left, rect.top);
|
||||
}
|
||||
m_ctx->CopySubresourceRegion(*(GSTexture11*)dTex, 0, x, y, 0, *(GSTexture11*)sTex, 0, pBox);
|
||||
}
|
||||
|
||||
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
|
||||
@@ -2495,20 +2477,9 @@ D3D_SHADER_MACRO* GSDevice11::ShaderMacro::GetPtr()
|
||||
return (D3D_SHADER_MACRO*)mout.data();
|
||||
}
|
||||
|
||||
/// Checks that we weren't sent things we declared we don't support
|
||||
/// Clears things we don't support that can be quietly disabled
|
||||
static void preprocessSel(GSDevice11::PSSelector& sel)
|
||||
{
|
||||
pxAssert(sel.write_rg == 0); // Not supported, shouldn't be sent
|
||||
}
|
||||
|
||||
void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
{
|
||||
pxAssert(!config.require_full_barrier); // We always specify no support so it shouldn't request this
|
||||
preprocessSel(config.ps);
|
||||
|
||||
GSVector2i rtsize = (config.rt ? config.rt : config.ds)->GetSize();
|
||||
|
||||
const GSVector2i rtsize = (config.rt ? config.rt : config.ds)->GetSize();
|
||||
GSTexture* colclip_rt = g_gs_device->GetColorClipTexture();
|
||||
|
||||
if (colclip_rt)
|
||||
@@ -2560,7 +2531,8 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
StretchRect(colclip_rt ? colclip_rt : config.rt, GSVector4(config.drawarea) / GSVector4(rtsize).xyxy(),
|
||||
primid_tex, GSVector4(config.drawarea), m_date.primid_init_ps[static_cast<u8>(config.datm)].get(), nullptr, false);
|
||||
}
|
||||
else if (config.destination_alpha != GSHWDrawConfig::DestinationAlphaMode::Off)
|
||||
else if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::Stencil ||
|
||||
config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne)
|
||||
{
|
||||
const GSVector4 src = GSVector4(config.drawarea) / GSVector4(config.ds->GetSize()).xyxy();
|
||||
const GSVector4 dst = src * 2.0f - 1.0f;
|
||||
@@ -2630,20 +2602,33 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
PSSetShaderResource(1, config.pal);
|
||||
}
|
||||
|
||||
GSTexture* rt_copy = nullptr;
|
||||
if (config.require_one_barrier || (config.tex && config.tex == config.rt)) // Used as "bind rt" flag when texture barrier is unsupported.
|
||||
GSTexture* draw_rt_clone = nullptr;
|
||||
|
||||
if (config.require_one_barrier || (config.tex && config.tex == config.rt))
|
||||
{
|
||||
// Bind the RT.This way special effect can use it.
|
||||
// Do not always bind the rt when it's not needed,
|
||||
// only bind it when effects use it such as fbmask emulation currently
|
||||
// because we copy the frame buffer and it is quite slow.
|
||||
CloneTexture(colclip_rt ? colclip_rt : config.rt, &rt_copy, config.drawarea);
|
||||
if (rt_copy)
|
||||
// Requires a copy of the RT.
|
||||
// Used as "bind rt" flag when texture barrier is unsupported for tex is fb.
|
||||
draw_rt_clone = CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true);
|
||||
if (draw_rt_clone)
|
||||
{
|
||||
CopyRect(colclip_rt ? colclip_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
|
||||
if (config.require_one_barrier)
|
||||
PSSetShaderResource(2, rt_copy);
|
||||
PSSetShaderResource(2, draw_rt_clone);
|
||||
if (config.tex && config.tex == config.rt)
|
||||
PSSetShaderResource(0, rt_copy);
|
||||
PSSetShaderResource(0, draw_rt_clone);
|
||||
}
|
||||
}
|
||||
|
||||
GSTexture* draw_ds_clone = nullptr;
|
||||
|
||||
if (config.tex && config.tex == config.ds)
|
||||
{
|
||||
// DX requires a copy when sampling the depth buffer.
|
||||
draw_ds_clone = CreateDepthStencil(rtsize.x, rtsize.y, config.ds->GetFormat(), false);
|
||||
if (draw_ds_clone)
|
||||
{
|
||||
CopyRect(config.ds, draw_ds_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
|
||||
PSSetShaderResource(0, draw_ds_clone);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2681,7 +2666,6 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
|
||||
if (config.alpha_second_pass.enable)
|
||||
{
|
||||
preprocessSel(config.alpha_second_pass.ps);
|
||||
if (config.cb_ps.FogColor_AREF.a != config.alpha_second_pass.ps_aref)
|
||||
{
|
||||
config.cb_ps.FogColor_AREF.a = config.alpha_second_pass.ps_aref;
|
||||
@@ -2697,8 +2681,12 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
DrawIndexedPrimitive();
|
||||
}
|
||||
|
||||
if (rt_copy)
|
||||
Recycle(rt_copy);
|
||||
if (draw_rt_clone)
|
||||
Recycle(draw_rt_clone);
|
||||
|
||||
if (draw_ds_clone)
|
||||
Recycle(draw_ds_clone);
|
||||
|
||||
if (primid_tex)
|
||||
Recycle(primid_tex);
|
||||
|
||||
|
||||
@@ -291,7 +291,6 @@ public:
|
||||
std::unique_ptr<GSDownloadTexture> CreateDownloadTexture(u32 width, u32 height, GSTexture::Format format) override;
|
||||
|
||||
void CommitClear(GSTexture* t);
|
||||
void CloneTexture(GSTexture* src, GSTexture** dest, const GSVector4i& rect);
|
||||
|
||||
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override;
|
||||
|
||||
|
||||
@@ -3828,6 +3828,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
GSTexture12* draw_rt = static_cast<GSTexture12*>(config.rt);
|
||||
GSTexture12* draw_ds = static_cast<GSTexture12*>(config.ds);
|
||||
GSTexture12* draw_rt_clone = nullptr;
|
||||
GSTexture12* draw_ds_clone = nullptr;
|
||||
|
||||
// Align the render area to 128x128, hopefully avoiding render pass restarts for small render area changes (e.g. Ratchet and Clank).
|
||||
const GSVector2i rtsize(config.rt ? config.rt->GetSize() : config.ds->GetSize());
|
||||
@@ -3883,7 +3884,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
// bind textures before checking the render pass, in case we need to transition them
|
||||
if (config.tex)
|
||||
{
|
||||
PSSetShaderResource(0, config.tex, config.tex != config.rt);
|
||||
PSSetShaderResource(0, config.tex, config.tex != config.rt && config.tex != config.ds);
|
||||
PSSetSampler(config.sampler);
|
||||
}
|
||||
if (config.pal)
|
||||
@@ -3907,15 +3908,16 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
}
|
||||
|
||||
if (config.require_one_barrier || (config.tex && config.tex == config.rt)) // Used as "bind rt" flag when texture barrier is unsupported.
|
||||
if (config.require_one_barrier || (config.tex && config.tex == config.rt))
|
||||
{
|
||||
// requires a copy of the RT
|
||||
// Requires a copy of the RT.
|
||||
// Used as "bind rt" flag when texture barrier is unsupported for tex is fb.
|
||||
draw_rt_clone = static_cast<GSTexture12*>(CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true));
|
||||
if (draw_rt_clone)
|
||||
{
|
||||
EndRenderPass();
|
||||
|
||||
GL_PUSH("Copy RT to temp texture for fbmask {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
|
||||
GL_PUSH("Copy RT to temp texture {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
|
||||
config.drawarea.width(), config.drawarea.height());
|
||||
|
||||
draw_rt_clone->SetState(GSTexture::State::Invalidated);
|
||||
@@ -3927,6 +3929,23 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
}
|
||||
|
||||
if (config.tex && config.tex == config.ds)
|
||||
{
|
||||
// DX requires a copy when sampling the depth buffer.
|
||||
draw_ds_clone = static_cast<GSTexture12*>(CreateDepthStencil(rtsize.x, rtsize.y, config.ds->GetFormat(), false));
|
||||
if (draw_ds_clone)
|
||||
{
|
||||
EndRenderPass();
|
||||
|
||||
GL_PUSH("Copy RT to temp texture {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
|
||||
config.drawarea.width(), config.drawarea.height());
|
||||
|
||||
draw_ds_clone->SetState(GSTexture::State::Invalidated);
|
||||
CopyRect(config.ds, draw_ds_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
|
||||
PSSetShaderResource(0, draw_ds_clone, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Switch to colclip target for colclip hw rendering
|
||||
if (pipe.ps.colclip_hw)
|
||||
{
|
||||
@@ -4073,6 +4092,9 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
if (draw_rt_clone)
|
||||
Recycle(draw_rt_clone);
|
||||
|
||||
if (draw_ds_clone)
|
||||
Recycle(draw_ds_clone);
|
||||
|
||||
if (date_image)
|
||||
Recycle(date_image);
|
||||
|
||||
|
||||
@@ -1037,7 +1037,7 @@ float GSRendererHW::GetTextureScaleFactor()
|
||||
return GetUpscaleMultiplier();
|
||||
}
|
||||
|
||||
GSVector2i GSRendererHW::GetValidSize(const GSTextureCache::Source* tex)
|
||||
GSVector2i GSRendererHW::GetValidSize(const GSTextureCache::Source* tex, const bool is_shuffle)
|
||||
{
|
||||
// Don't blindly expand out to the scissor size if we're not drawing to it.
|
||||
// e.g. Burnout 3, God of War II, etc.
|
||||
@@ -1088,10 +1088,9 @@ GSVector2i GSRendererHW::GetValidSize(const GSTextureCache::Source* tex)
|
||||
// Early detection of texture shuffles. These double the input height because they're interpreting 64x32 C32 pages as 64x64 C16.
|
||||
// Why? Well, we don't want to be doubling the heights of targets, but also we don't want to align C32 targets to 64 instead of 32.
|
||||
// Yumeria's text breaks, and GOW goes to 512x448 instead of 512x416 if we don't.
|
||||
const bool possible_texture_shuffle =
|
||||
(tex && m_vt.m_primclass == GS_SPRITE_CLASS && frame_psm.bpp == 16 &&
|
||||
const bool possible_texture_shuffle = tex && m_vt.m_primclass == GS_SPRITE_CLASS && frame_psm.bpp == 16 &&
|
||||
GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16 &&
|
||||
(tex->m_32_bits_fmt ||
|
||||
(is_shuffle || (tex->m_32_bits_fmt ||
|
||||
(m_cached_ctx.TEX0.TBP0 != m_cached_ctx.FRAME.Block() && IsOpaque() && !(m_context->TEX1.MMIN & 1) &&
|
||||
m_cached_ctx.FRAME.FBMSK && g_texture_cache->Has32BitTarget(m_cached_ctx.FRAME.Block()))));
|
||||
if (possible_texture_shuffle)
|
||||
@@ -1128,9 +1127,9 @@ GSVector2i GSRendererHW::GetValidSize(const GSTextureCache::Source* tex)
|
||||
return GSVector2i(width, height);
|
||||
}
|
||||
|
||||
GSVector2i GSRendererHW::GetTargetSize(const GSTextureCache::Source* tex, const bool can_expand)
|
||||
GSVector2i GSRendererHW::GetTargetSize(const GSTextureCache::Source* tex, const bool can_expand, const bool is_shuffle)
|
||||
{
|
||||
const GSVector2i valid_size = GetValidSize(tex);
|
||||
const GSVector2i valid_size = GetValidSize(tex, is_shuffle);
|
||||
|
||||
return g_texture_cache->GetTargetSize(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, valid_size.x, valid_size.y, can_expand);
|
||||
}
|
||||
@@ -2860,7 +2859,8 @@ void GSRendererHW::Draw()
|
||||
(m_vt.m_primclass == GS_SPRITE_CLASS || (m_vt.m_primclass == GS_TRIANGLE_CLASS && (m_index.tail % 6) == 0 && TrianglesAreQuads(true) && m_index.tail > 6)))
|
||||
{
|
||||
// Tail check is to make sure we have enough strips to go all the way across the page, or if it's using a region clamp could be used to draw strips.
|
||||
if (GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16 && (m_index.tail >= (m_cached_ctx.TEX0.TBW * 2) || m_cached_ctx.CLAMP.WMS > CLAMP_CLAMP || m_cached_ctx.CLAMP.WMT > CLAMP_CLAMP))
|
||||
if (GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16 &&
|
||||
(m_index.tail >= (m_cached_ctx.TEX0.TBW * 2) || m_cached_ctx.TEX0.TBP0 == m_cached_ctx.FRAME.Block() || m_cached_ctx.CLAMP.WMS > CLAMP_CLAMP || m_cached_ctx.CLAMP.WMT > CLAMP_CLAMP))
|
||||
{
|
||||
const GSVertex* v = &m_vertex.buff[0];
|
||||
|
||||
@@ -2884,21 +2884,45 @@ void GSRendererHW::Draw()
|
||||
}
|
||||
|
||||
// It's possible it's writing to an old 32bit target, but is actually just a 16bit copy, so let's make sure it's actually using a mask.
|
||||
if (!shuffle_target && m_cached_ctx.FRAME.FBMSK)
|
||||
if (!shuffle_target)
|
||||
{
|
||||
// FBW is going to be wrong for channel shuffling into a new target, so take it from the source.
|
||||
FRAME_TEX0.U64 = 0;
|
||||
FRAME_TEX0.TBP0 = m_cached_ctx.FRAME.Block();
|
||||
FRAME_TEX0.TBW = m_cached_ctx.FRAME.FBW;
|
||||
FRAME_TEX0.PSM = m_cached_ctx.FRAME.PSM;
|
||||
bool shuffle_channel_reads = !m_cached_ctx.FRAME.FBMSK;
|
||||
const u32 increment = (m_vt.m_primclass == GS_TRIANGLE_CLASS) ? 3 : 2;
|
||||
const GSVertex* v = &m_vertex.buff[0];
|
||||
|
||||
GSTextureCache::Target* tgt = g_texture_cache->LookupTarget(FRAME_TEX0, GSVector2i(m_vt.m_max.p.x, m_vt.m_max.p.y), GetTextureScaleFactor(), GSTextureCache::RenderTarget, false,
|
||||
fm, false, false, false, false, GSVector4i::zero(), true);
|
||||
if (shuffle_channel_reads)
|
||||
{
|
||||
for (u32 i = 0; i < m_index.tail; i += increment)
|
||||
{
|
||||
const int first_u = (PRIM->FST ? v[i].U : static_cast<int>(v[i].ST.S / v[(increment == 2) ? i + 1 : i].RGBAQ.Q)) >> 4;
|
||||
const int second_u = (PRIM->FST ? v[i + 1].U : static_cast<int>(v[i + 1].ST.S / v[i + 1].RGBAQ.Q)) >> 4;
|
||||
const int vector_width = std::abs(v[i + 1].XYZ.X - v[i].XYZ.X) / 16;
|
||||
const int tex_width = std::abs(second_u - first_u);
|
||||
// & 7 just a quicker way of doing % 8
|
||||
if ((vector_width & 7) != 0 || (tex_width & 7) != 0 || tex_width != vector_width)
|
||||
{
|
||||
shuffle_channel_reads = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_cached_ctx.FRAME.FBMSK || shuffle_channel_reads)
|
||||
{
|
||||
// FBW is going to be wrong for channel shuffling into a new target, so take it from the source.
|
||||
FRAME_TEX0.U64 = 0;
|
||||
FRAME_TEX0.TBP0 = m_cached_ctx.FRAME.Block();
|
||||
FRAME_TEX0.TBW = m_cached_ctx.FRAME.FBW;
|
||||
FRAME_TEX0.PSM = m_cached_ctx.FRAME.PSM;
|
||||
|
||||
if (tgt)
|
||||
shuffle_target = tgt->m_32_bits_fmt;
|
||||
GSTextureCache::Target* tgt = g_texture_cache->FindOverlappingTarget(FRAME_TEX0.TBP0, GSLocalMemory::GetEndBlockAddress(FRAME_TEX0.TBP0, FRAME_TEX0.TBW, FRAME_TEX0.PSM, m_r));
|
||||
|
||||
tgt = nullptr;
|
||||
if (tgt)
|
||||
shuffle_target = tgt->m_32_bits_fmt;
|
||||
else
|
||||
shuffle_target = shuffle_channel_reads;
|
||||
|
||||
tgt = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2942,7 +2966,13 @@ void GSRendererHW::Draw()
|
||||
if (possible_shuffle && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp != 16)
|
||||
possible_shuffle &= draw_uses_target;
|
||||
|
||||
possible_shuffle &= src && (src->m_from_target != nullptr || (m_skip && possible_shuffle));
|
||||
const bool shuffle_source = possible_shuffle && src && ((src->m_from_target != nullptr && GSLocalMemory::m_psm[src->m_from_target->m_TEX0.PSM].bpp != 16) || m_skip);
|
||||
|
||||
if (!shuffle_source && possible_shuffle)
|
||||
{
|
||||
const bool is_16bit_copy = m_cached_ctx.TEX0.TBP0 != m_cached_ctx.FRAME.Block() && shuffle_target && IsOpaque() && !(context->TEX1.MMIN & 1) && !src->m_32_bits_fmt && m_cached_ctx.FRAME.FBMSK;
|
||||
possible_shuffle &= is_16bit_copy || (m_cached_ctx.TEX0.TBP0 == m_cached_ctx.FRAME.Block() && shuffle_target);
|
||||
}
|
||||
// We don't know the alpha range of direct sources when we first tried to optimize the alpha test.
|
||||
// Moving the texture lookup before the ATST optimization complicates things a lot, so instead,
|
||||
// recompute it, and everything derived from it again if it changes.
|
||||
@@ -2988,7 +3018,7 @@ void GSRendererHW::Draw()
|
||||
const bool can_expand = !(m_cached_ctx.ZBUF.ZMSK && output_black);
|
||||
|
||||
// Estimate size based on the scissor rectangle and height cache.
|
||||
GSVector2i t_size = GetTargetSize(src, can_expand);
|
||||
GSVector2i t_size = GetTargetSize(src, can_expand, possible_shuffle);
|
||||
const GSVector4i t_size_rect = GSVector4i::loadh(t_size);
|
||||
|
||||
// Ensure draw rect is clamped to framebuffer size. Necessary for updating valid area.
|
||||
@@ -3077,7 +3107,7 @@ void GSRendererHW::Draw()
|
||||
|
||||
if (!ds && m_cached_ctx.FRAME.FBP != m_cached_ctx.ZBUF.ZBP)
|
||||
{
|
||||
ds = g_texture_cache->CreateTarget(ZBUF_TEX0, t_size, GetValidSize(src), target_scale, GSTextureCache::DepthStencil,
|
||||
ds = g_texture_cache->CreateTarget(ZBUF_TEX0, t_size, GetValidSize(src, possible_shuffle), target_scale, GSTextureCache::DepthStencil,
|
||||
true, 0, false, force_preload, preserve_depth, m_r, src);
|
||||
if (!ds) [[unlikely]]
|
||||
{
|
||||
@@ -3228,7 +3258,7 @@ void GSRendererHW::Draw()
|
||||
return;
|
||||
}
|
||||
|
||||
rt = g_texture_cache->CreateTarget(FRAME_TEX0, t_size, GetValidSize(src), (GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off && scale_draw < 0 && is_possible_mem_clear != ClearType::NormalClear) ? src->m_from_target->GetScale() : target_scale,
|
||||
rt = g_texture_cache->CreateTarget(FRAME_TEX0, t_size, GetValidSize(src, possible_shuffle), (GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off && scale_draw < 0 && is_possible_mem_clear != ClearType::NormalClear) ? src->m_from_target->GetScale() : target_scale,
|
||||
GSTextureCache::RenderTarget, true, fm, false, force_preload, preserve_rt_color || possible_shuffle, lookup_rect, src);
|
||||
|
||||
if (!rt) [[unlikely]]
|
||||
@@ -3242,6 +3272,49 @@ void GSRendererHW::Draw()
|
||||
{
|
||||
rt->UpdateValidity(GSVector4i::loadh(GSVector2i(GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.x, GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.y)), true);
|
||||
}
|
||||
|
||||
if (src && !src->m_from_target && GSLocalMemory::m_psm[src->m_TEX0.PSM].bpp == GSLocalMemory::m_psm[m_context->FRAME.PSM].bpp &&
|
||||
(GSUtil::GetChannelMask(src->m_TEX0.PSM) & GSUtil::GetChannelMask(m_context->FRAME.PSM)) != 0)
|
||||
{
|
||||
const u32 draw_end = GSLocalMemory::GetEndBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r) + 1;
|
||||
const u32 draw_start = GSLocalMemory::GetStartBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r);
|
||||
|
||||
if (draw_start <= src->m_TEX0.TBP0 && draw_end > src->m_TEX0.TBP0)
|
||||
{
|
||||
g_texture_cache->ReplaceSourceTexture(src, rt->GetTexture(), rt->GetScale(), rt->GetUnscaledSize(), nullptr, true);
|
||||
|
||||
src->m_from_target = rt;
|
||||
src->m_from_target_TEX0 = rt->m_TEX0;
|
||||
src->m_target_direct = true;
|
||||
src->m_shared_texture = true;
|
||||
src->m_target = true;
|
||||
src->m_texture = rt->m_texture;
|
||||
src->m_32_bits_fmt = rt->m_32_bits_fmt;
|
||||
src->m_valid_rect = rt->m_valid;
|
||||
src->m_alpha_minmax.first = rt->m_alpha_min;
|
||||
src->m_alpha_minmax.second = rt->m_alpha_max;
|
||||
|
||||
const int target_width = std::max(FRAME_TEX0.TBW, 1U);
|
||||
const int page_offset = (src->m_TEX0.TBP0 - rt->m_TEX0.TBP0) >> 5;
|
||||
const int vertical_page_offset = page_offset / target_width;
|
||||
const int horizontal_page_offset = page_offset - (vertical_page_offset * target_width);
|
||||
|
||||
if (vertical_page_offset)
|
||||
{
|
||||
const int height = std::max(rt->m_valid.w, possible_shuffle ? (m_r.w / 2) : m_r.w);
|
||||
src->m_region.SetY(vertical_page_offset * GSLocalMemory::m_psm[rt->m_TEX0.PSM].pgs.y, height);
|
||||
}
|
||||
if (horizontal_page_offset)
|
||||
src->m_region.SetX(horizontal_page_offset * GSLocalMemory::m_psm[rt->m_TEX0.PSM].pgs.x, target_width * GSLocalMemory::m_psm[rt->m_TEX0.PSM].pgs.x);
|
||||
|
||||
if (rt->m_dirty.empty())
|
||||
{
|
||||
RGBAMask rgba_mask;
|
||||
rgba_mask._u32 = GSUtil::GetChannelMask(rt->m_TEX0.PSM);
|
||||
g_texture_cache->AddDirtyRectTarget(rt, m_r, FRAME_TEX0.PSM, FRAME_TEX0.TBW, rgba_mask, GSLocalMemory::m_psm[FRAME_TEX0.PSM].trbpp >= 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rt->m_TEX0.TBP0 != m_cached_ctx.FRAME.Block())
|
||||
{
|
||||
@@ -3349,38 +3422,32 @@ void GSRendererHW::Draw()
|
||||
t_size.x = rt->m_unscaled_size.x - horizontal_offset;
|
||||
t_size.y = rt->m_unscaled_size.y - vertical_offset;
|
||||
}
|
||||
|
||||
// Don't resize if the BPP don't match.
|
||||
if (frame_psm.bpp == GSLocalMemory::m_psm[rt->m_TEX0.PSM].bpp)
|
||||
GSVector2i new_size = GetValidSize(src, possible_shuffle);
|
||||
if (new_size.x > rt->m_unscaled_size.x || new_size.y > rt->m_unscaled_size.y)
|
||||
{
|
||||
if (m_r.w > rt->m_unscaled_size.y || m_r.z > rt->m_unscaled_size.x)
|
||||
const u32 new_width = std::max(new_size.x, rt->m_unscaled_size.x);
|
||||
const u32 new_height = std::max(new_size.y, rt->m_unscaled_size.y);
|
||||
|
||||
//DevCon.Warning("HW: Resizing texture %d x %d draw %d", rt->m_unscaled_size.x, new_height, s_n);
|
||||
rt->ResizeTexture(new_width, new_height);
|
||||
}
|
||||
else if ((IsPageCopy() || is_possible_mem_clear) && m_r.width() <= frame_psm.pgs.x && m_r.height() <= frame_psm.pgs.y)
|
||||
{
|
||||
const int get_next_ctx = m_env.PRIM.CTXT;
|
||||
const GSDrawingContext& next_ctx = m_env.CTXT[get_next_ctx];
|
||||
GSVector4i update_valid = GSVector4i::loadh(GSVector2i(horizontal_offset + GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.x, GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.y + vertical_offset));
|
||||
rt->UpdateValidity(update_valid, true);
|
||||
if (is_possible_mem_clear)
|
||||
{
|
||||
const u32 new_height = std::max(m_r.w, rt->m_unscaled_size.y);
|
||||
const u32 new_width = std::max(m_r.z, rt->m_unscaled_size.x);
|
||||
|
||||
//DevCon.Warning("HW: Resizing texture %d x %d draw %d", rt->m_unscaled_size.x, new_height, s_n);
|
||||
rt->ResizeTexture(new_width, new_height);
|
||||
|
||||
const bool frame_masked = ((m_cached_ctx.FRAME.FBMSK & frame_psm.fmsk) == frame_psm.fmsk) || (m_cached_ctx.TEST.ATE && m_cached_ctx.TEST.ATST == ATST_NEVER && !(m_cached_ctx.TEST.AFAIL & AFAIL_FB_ONLY));
|
||||
|
||||
rt->UpdateValidity(m_r, !frame_masked);
|
||||
rt->UpdateDrawn(m_r, !frame_masked);
|
||||
}
|
||||
else if ((IsPageCopy() || is_possible_mem_clear) && m_r.width() <= frame_psm.pgs.x && m_r.height() <= frame_psm.pgs.y)
|
||||
{
|
||||
const int get_next_ctx = m_env.PRIM.CTXT;
|
||||
const GSDrawingContext& next_ctx = m_env.CTXT[get_next_ctx];
|
||||
GSVector4i update_valid = GSVector4i::loadh(GSVector2i(horizontal_offset + GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.x, GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.y + vertical_offset));
|
||||
rt->UpdateValidity(update_valid, true);
|
||||
if (is_possible_mem_clear)
|
||||
if ((horizontal_offset + GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.x) >= static_cast<int>(rt->m_TEX0.TBW * 64) && next_ctx.FRAME.Block() == (m_cached_ctx.FRAME.Block() + 0x20))
|
||||
{
|
||||
if ((horizontal_offset + GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.x) >= static_cast<int>(rt->m_TEX0.TBW * 64) && next_ctx.FRAME.Block() == (m_cached_ctx.FRAME.Block() + 0x20))
|
||||
{
|
||||
update_valid.x = 0;
|
||||
update_valid.z = GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.x;
|
||||
update_valid.y += GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.y;
|
||||
update_valid.w += GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.y;
|
||||
rt->UpdateValidity(update_valid, true);
|
||||
}
|
||||
update_valid.x = 0;
|
||||
update_valid.z = GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.x;
|
||||
update_valid.y += GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.y;
|
||||
update_valid.w += GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.y;
|
||||
rt->UpdateValidity(update_valid, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3539,7 +3606,7 @@ void GSRendererHW::Draw()
|
||||
// This should never happen, but just to be safe..
|
||||
if (!ds)
|
||||
{
|
||||
ds = g_texture_cache->CreateTarget(ZBUF_TEX0, t_size, GetValidSize(src), target_scale, GSTextureCache::DepthStencil,
|
||||
ds = g_texture_cache->CreateTarget(ZBUF_TEX0, t_size, GetValidSize(src, possible_shuffle), target_scale, GSTextureCache::DepthStencil,
|
||||
true, 0, false, force_preload, preserve_depth, m_r, src);
|
||||
if (!ds) [[unlikely]]
|
||||
{
|
||||
@@ -5986,10 +6053,9 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
// Switch DATE_PRIMID with DATE_BARRIER in such cases to ensure accuracy.
|
||||
// No mix of COLCLIP + sw blend + DATE_PRIMID, neither sw fbmask + DATE_PRIMID.
|
||||
// Note: Do the swap in the end, saves the expensive draw splitting/barriers when mixed software blending is used.
|
||||
if (sw_blending && DATE_PRIMID && m_conf.require_full_barrier)
|
||||
if (sw_blending && DATE_PRIMID && features.texture_barrier && m_conf.require_full_barrier)
|
||||
{
|
||||
GL_PERF("DATE: Swap DATE_PRIMID with DATE_BARRIER");
|
||||
m_conf.require_full_barrier = true;
|
||||
DATE_PRIMID = false;
|
||||
DATE_BARRIER = true;
|
||||
}
|
||||
@@ -7404,7 +7470,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
if (m_conf.destination_alpha >= GSHWDrawConfig::DestinationAlphaMode::Stencil &&
|
||||
m_conf.destination_alpha <= GSHWDrawConfig::DestinationAlphaMode::StencilOne && !m_conf.ds)
|
||||
{
|
||||
const bool is_one_barrier = (m_conf.require_full_barrier && (m_prim_overlap == PRIM_OVERLAP_NO || m_conf.ps.shuffle || m_channel_shuffle));
|
||||
const bool is_one_barrier = (features.texture_barrier && m_conf.require_full_barrier && (m_prim_overlap == PRIM_OVERLAP_NO || m_conf.ps.shuffle || m_channel_shuffle));
|
||||
if ((temp_ds.reset(g_gs_device->CreateDepthStencil(m_conf.rt->GetWidth(), m_conf.rt->GetHeight(), GSTexture::Format::DepthStencil, false)), temp_ds))
|
||||
{
|
||||
m_conf.ds = temp_ds.get();
|
||||
@@ -7580,11 +7646,17 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
pxAssert(!m_conf.require_full_barrier || !m_conf.ps.colclip_hw);
|
||||
|
||||
// Swap full barrier for one barrier when there's no overlap, or a shuffle.
|
||||
if (m_conf.require_full_barrier && (m_prim_overlap == PRIM_OVERLAP_NO || m_conf.ps.shuffle || m_channel_shuffle))
|
||||
if (features.texture_barrier && m_conf.require_full_barrier && (m_prim_overlap == PRIM_OVERLAP_NO || m_conf.ps.shuffle || m_channel_shuffle))
|
||||
{
|
||||
m_conf.require_full_barrier = false;
|
||||
m_conf.require_one_barrier = true;
|
||||
}
|
||||
else if (!features.texture_barrier)
|
||||
{
|
||||
// These shouldn't be enabled if texture barriers aren't supported, make sure they are off.
|
||||
m_conf.ps.write_rg = 0;
|
||||
m_conf.require_full_barrier = false;
|
||||
}
|
||||
|
||||
// rs
|
||||
const GSVector4i hacked_scissor = m_channel_shuffle ? GSVector4i::cxpr(0, 0, 1024, 1024) : m_context->scissor.in;
|
||||
@@ -9049,10 +9121,7 @@ void GSRendererHW::EndHLEHardwareDraw(bool force_copy_on_hazard /* = false */)
|
||||
return;
|
||||
}
|
||||
|
||||
// DX11 can't partial copy depth textures.
|
||||
const GSVector4i copy_rect = (src->IsDepthStencil() && !features.test_and_sample_depth) ?
|
||||
src->GetRect() :
|
||||
config.drawarea.rintersect(src->GetRect());
|
||||
const GSVector4i copy_rect = config.drawarea.rintersect(src->GetRect());
|
||||
g_gs_device->CopyRect(src, copy, copy_rect - copy_rect.xyxy(), copy_rect.x, copy_rect.y);
|
||||
config.tex = copy;
|
||||
}
|
||||
|
||||
@@ -222,8 +222,8 @@ public:
|
||||
GSVector4i ComputeBoundingBox(const GSVector2i& rtsize, float rtscale);
|
||||
void MergeSprite(GSTextureCache::Source* tex);
|
||||
float GetTextureScaleFactor() override;
|
||||
GSVector2i GetValidSize(const GSTextureCache::Source* tex = nullptr);
|
||||
GSVector2i GetTargetSize(const GSTextureCache::Source* tex = nullptr, const bool can_expand = true);
|
||||
GSVector2i GetValidSize(const GSTextureCache::Source* tex = nullptr, const bool is_shuffle = false);
|
||||
GSVector2i GetTargetSize(const GSTextureCache::Source* tex = nullptr, const bool can_expand = true, const bool is_shuffle = false);
|
||||
|
||||
void Reset(bool hardware_reset) override;
|
||||
void UpdateSettings(const Pcsx2Config::GSOptions& old_config) override;
|
||||
|
||||
@@ -1408,16 +1408,31 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
|
||||
if (rect_clean)
|
||||
{
|
||||
bool can_use = true;
|
||||
for (auto& dirty : t->m_dirty)
|
||||
{
|
||||
const GSVector4i dirty_rect = dirty.GetDirtyRect(t->m_TEX0, t->m_TEX0.PSM != dirty.psm);
|
||||
if (!dirty_rect.rintersect(new_rect).rempty())
|
||||
{
|
||||
rect_clean = false;
|
||||
partial |= !new_rect.rintersect(dirty_rect).eq(new_rect) || dirty_rect.eq(new_rect);
|
||||
|
||||
if(!dirty_rect.rintersect(t->m_valid).eq(t->m_valid) || GSUtil::GetChannelMask(t->m_TEX0.PSM) != t->m_dirty.GetDirtyChannels())
|
||||
partial |= !new_rect.rintersect(dirty_rect).eq(new_rect) || dirty_rect.eq(new_rect);
|
||||
else // Nothing is valid anymore, kill it.
|
||||
{
|
||||
can_use = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!can_use)
|
||||
{
|
||||
InvalidateSourcesFromTarget(t);
|
||||
i = list.erase(i);
|
||||
delete t;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const u32 channel_mask = GSUtil::GetChannelMask(psm);
|
||||
@@ -1681,22 +1696,27 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
u32 src_psm = psm;
|
||||
|
||||
// If the input is C16 and it's actually a shuffle of 32bits we need to correct the size.
|
||||
if ((tex_color_psm & 0xF) <= PSMCT24 && (psm & 0x7) == PSMCT16 && possible_shuffle)
|
||||
if ((tex_color_psm & 0xF) <= PSMCT24 && (psm & 0x7) == PSMCT16)
|
||||
{
|
||||
src_psm = t->m_TEX0.PSM;
|
||||
// If it's taking double width for the shuffle, half that.
|
||||
if (src_bw == (rt_tbw * 2))
|
||||
if (possible_shuffle)
|
||||
{
|
||||
src_bw = rt_tbw;
|
||||
src_psm = t->m_TEX0.PSM;
|
||||
// If it's taking double width for the shuffle, half that.
|
||||
if (src_bw == (rt_tbw * 2))
|
||||
{
|
||||
src_bw = rt_tbw;
|
||||
|
||||
rect.x /= 2;
|
||||
rect.z /= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.y /= 2;
|
||||
rect.w /= 2;
|
||||
rect.x /= 2;
|
||||
rect.z /= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.y /= 2;
|
||||
rect.w /= 2;
|
||||
}
|
||||
}
|
||||
else // Formats are not compatible for normal draws, only shuffles.
|
||||
continue;
|
||||
}
|
||||
if (bp > t->m_TEX0.TBP0)
|
||||
{
|
||||
@@ -2340,11 +2360,11 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
lookup_rect = lookup_rect & GSVector4i(~8);
|
||||
|
||||
const GSVector4i translated_rect = GSVector4i(0, 0, 0, 0).max_i32(TranslateAlignedRectByPage(t, TEX0.TBP0, TEX0.PSM, TEX0.TBW, lookup_rect));
|
||||
const GSVector4i dirty_rect = t->m_dirty.empty() ? GSVector4i::zero() : t->m_dirty.GetTotalRect(t->m_TEX0, t->m_unscaled_size).rintersect(t->m_valid);
|
||||
const GSVector4i dirty_rect = t->m_dirty.empty() ? GSVector4i::zero() : t->m_dirty.GetTotalRect(t->m_TEX0, t->m_unscaled_size);
|
||||
const bool all_dirty = dirty_rect.eq(t->m_valid);
|
||||
|
||||
|
||||
if (!is_shuffle && !t->m_dirty.empty() && (!preserve_alpha && !preserve_rgb) && (GSState::s_n - 1) != t->m_last_draw)
|
||||
if (!is_shuffle && !dirty_rect.rempty() && (!preserve_alpha && !preserve_rgb) && (GSState::s_n - 3) > t->m_last_draw)
|
||||
{
|
||||
GL_INS("TC: Deleting RT BP 0x%x BW %d PSM %s due to dirty areas not preserved (Likely change in target)", t->m_TEX0.TBP0, t->m_TEX0.TBW, psm_str(t->m_TEX0.PSM));
|
||||
InvalidateSourcesFromTarget(t);
|
||||
@@ -2354,7 +2374,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!all_dirty && ((translated_rect.w <= t->m_valid.w) || widthpage_offset == 0 || (GSState::s_n - 1) == t->m_last_draw))
|
||||
if (!all_dirty && ((translated_rect.w <= t->m_valid.w) || widthpage_offset == 0 || (GSState::s_n - 3) <= t->m_last_draw))
|
||||
{
|
||||
if (TEX0.TBW == t->m_TEX0.TBW && !is_shuffle && widthpage_offset == 0 && ((min_rect.w + 63) / 64) > 1)
|
||||
{
|
||||
@@ -3270,23 +3290,19 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons
|
||||
|
||||
if (buffer_width != std::max(1U, t->m_TEX0.TBW))
|
||||
{
|
||||
i++;
|
||||
// Check if this got messed with at some point, if it did just nuke it.
|
||||
if (t->m_valid.width() == dst->m_valid.width())
|
||||
if (!preserve_target && t->m_age > 0)
|
||||
{
|
||||
// Not correct, but it's better than a null reference.
|
||||
// Probably best we don't poke the beast if it's being used as the current source.
|
||||
if (src && src->m_target_direct && src->m_from_target == t)
|
||||
{
|
||||
DevCon.Warning("Replacing source target, texture may be invalid");
|
||||
src->m_texture = dst->m_texture;
|
||||
src->m_from_target = dst;
|
||||
}
|
||||
continue;
|
||||
|
||||
InvalidateSourcesFromTarget(t);
|
||||
i = list.erase(j);
|
||||
delete t;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
|
||||
continue;
|
||||
}
|
||||
// If the two targets are misaligned, it's likely a relocation, so we can just kill the old target.
|
||||
@@ -3924,7 +3940,7 @@ void GSTextureCache::InvalidateContainedTargets(u32 start_bp, u32 end_bp, u32 wr
|
||||
|
||||
const u32 offset = (std::abs(static_cast<int>(start_bp - t->m_TEX0.TBP0)) >> 5) % std::max(1U, t->m_TEX0.TBW);
|
||||
// If not fully contained but they are aligned and or clean, just dirty the area.
|
||||
if (start_bp != t->m_TEX0.TBP0 && (t->m_TEX0.TBP0 < start_bp || t->UnwrappedEndBlock() > end_bp) && (offset == 0 || t->m_dirty.size() == 0))
|
||||
if (type != DepthStencil && start_bp != t->m_TEX0.TBP0 && (t->m_TEX0.TBP0 < start_bp || t->UnwrappedEndBlock() > end_bp) && (offset == 0 || t->m_dirty.size() == 0))
|
||||
{
|
||||
if (write_bw == t->m_TEX0.TBW && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp == GSLocalMemory::m_psm[write_psm].bpp)
|
||||
{
|
||||
|
||||
@@ -2489,12 +2489,15 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
|
||||
if (config.require_one_barrier && !m_features.texture_barrier)
|
||||
{
|
||||
// Requires a copy of the RT
|
||||
// Requires a copy of the RT.
|
||||
draw_rt_clone = CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true);
|
||||
GL_PUSH("Copy RT to temp texture for fbmask {%d,%d %dx%d}",
|
||||
config.drawarea.left, config.drawarea.top,
|
||||
config.drawarea.width(), config.drawarea.height());
|
||||
CopyRect(colclip_rt ? colclip_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
|
||||
if (draw_rt_clone)
|
||||
{
|
||||
GL_PUSH("GL: Copy RT to temp texture {%d,%d %dx%d}",
|
||||
config.drawarea.left, config.drawarea.top,
|
||||
config.drawarea.width(), config.drawarea.height());
|
||||
CopyRect(colclip_rt ? colclip_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
|
||||
}
|
||||
}
|
||||
|
||||
IASetVertexBuffer(config.verts, config.nverts);
|
||||
@@ -2563,7 +2566,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
if (check_barrier && ((config.tex && (config.tex == config.ds || config.tex == config.rt)) || ((psel.ps.IsFeedbackLoop() || psel.ps.blend_c == 1) && GLState::rt == config.rt)))
|
||||
{
|
||||
// Ensure all depth writes are finished before sampling
|
||||
GL_INS("Texture barrier to flush depth or rt before reading");
|
||||
GL_INS("GL: Texture barrier to flush depth or rt before reading");
|
||||
glTextureBarrier();
|
||||
}
|
||||
// additional non-pipeline config stuff
|
||||
|
||||
@@ -394,6 +394,8 @@ __ri void ImGuiManager::DrawSettingsOverlay(float scale, float margin, float spa
|
||||
APPEND("IVU ");
|
||||
if (EmuConfig.Speedhacks.vuThread)
|
||||
APPEND("MTVU ");
|
||||
if (EmuConfig.GS.VsyncEnable)
|
||||
APPEND("VSYNC ");
|
||||
|
||||
APPEND("EER={} EEC={} VUR={} VUC={} VQS={} ", static_cast<unsigned>(EmuConfig.Cpu.FPUFPCR.GetRoundMode()),
|
||||
EmuConfig.Cpu.Recompiler.GetEEClampMode(), static_cast<unsigned>(EmuConfig.Cpu.VU0FPCR.GetRoundMode()),
|
||||
|
||||
Reference in New Issue
Block a user