Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79f4af8ab5 | ||
|
|
a5f83329cb | ||
|
|
267479f31d | ||
|
|
164462e510 | ||
|
|
6331df306f | ||
|
|
027ceebcbd | ||
|
|
edb2c0080c | ||
|
|
caafc87b29 | ||
|
|
5d37cac4a0 | ||
|
|
8f68e096d4 | ||
|
|
430cad48e3 | ||
|
|
757a9532e6 | ||
|
|
f26f8cafa9 | ||
|
|
128a79e355 | ||
|
|
cc2d99db3a | ||
|
|
30a31d931a | ||
|
|
1c30d449bf | ||
|
|
dc4ce58248 | ||
|
|
dc93e861c7 | ||
|
|
960daf27e2 | ||
|
|
844f21344d | ||
|
|
535ad110e3 | ||
|
|
0e0d7a5441 | ||
|
|
ed63221c7e | ||
|
|
f9c2d7767d | ||
|
|
cb91478590 | ||
|
|
5dec7fe27d | ||
|
|
575d487c65 | ||
|
|
2b9289f402 | ||
|
|
9273683d3c | ||
|
|
88f8465e7e | ||
|
|
f26031cada | ||
|
|
3352d71515 | ||
|
|
999f9532ee | ||
|
|
d1f62ca9bf | ||
|
|
ef9f0cf635 | ||
|
|
d745564451 | ||
|
|
d37ac992fc | ||
|
|
e7fc3de90c | ||
|
|
bde81380c3 | ||
|
|
839b482cb5 | ||
|
|
72f70d4789 | ||
|
|
d646bbf5c1 | ||
|
|
e68aaf6540 | ||
|
|
20ab5ed0fa | ||
|
|
8590e390a2 | ||
|
|
ab1d558420 | ||
|
|
53c9021455 |
@@ -537,6 +537,7 @@
|
||||
030000009b2800003200000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
|
||||
030000009b2800006000000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
|
||||
030000009b2800001800000000000000,Raphnet Jaguar Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,platform:Windows,
|
||||
030000009b2800006300000000000000,Raphnet N64 Adapter,a:b0,b:b1,start:b3,lefttrigger:b2,dpup:b10,dpleft:b12,dpdown:b11,dpright:b13,leftx:a0,lefty:a1,-rightx:b8,+rightx:b9,-righty:b6,+righty:b7,leftshoulder:b4,rightshoulder:b5,platform:Windows,
|
||||
030000009b2800000200000000000000,Raphnet NES Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows,
|
||||
030000009b2800004400000000000000,Raphnet PS1 and PS2 Adapter,a:b1,b:b2,back:b5,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b9,rightx:a3,righty:a4,start:b4,x:b0,y:b3,platform:Windows,
|
||||
030000009b2800004300000000000000,Raphnet Saturn,a:b0,b:b1,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
|
||||
@@ -663,6 +664,7 @@
|
||||
03000000c61100001000000000000000,Tencent Xianyou Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows,
|
||||
03000000790000002601000000000000,TGZ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000591c00002400000000000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000591c00002600000000000000,THEGamepad,a:b2,b:b1,back:b6,leftx:a0,lefty:a1,start:b7,x:b3,y:b0,platform:Windows,
|
||||
030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
|
||||
030000004f04000023b3000000000000,Thrustmaster Dual Trigger PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000004f0400000ed0000000000000,ThrustMaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
@@ -983,6 +985,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000457500002211000000010000,SZMY Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
03000000790000001c18000003100000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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:Mac OS X,
|
||||
03000000591c00002400000021000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000591c00002600000021000000,THEGamepad,a:b2,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Mac OS X,
|
||||
030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,
|
||||
030000004f0400000ed0000000020000,ThrustMaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,
|
||||
@@ -1332,7 +1335,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
050000007e0500003003000001000000,Nintendo Wii U Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
|
||||
030000000d0500000308000010010000,Nostromo n45 Dual Analog,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,
|
||||
050000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Linux,
|
||||
050000007e0500001920000001800000,NSO N64 Controller,a:b0,b:b1,guide:b11,misc1:b12,start:b6,leftshoulder:b3,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,-rightx:b9,+rightx:b10,-righty:b7,+righty:b8,lefttrigger:b2,righttrigger:b5,platform:Linux,
|
||||
050000007e0500001920000001800000,NSO N64 Controller,+rightx:b10,+righty:b8,-rightx:b9,-righty:b7,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b3,lefttrigger:b2,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b4,righttrigger:b5,start:b6,platform:Linux,
|
||||
050000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
|
||||
03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000550900001472000011010000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
|
||||
|
||||
@@ -128,11 +128,12 @@ ProcessedVertex load_vertex(uint index)
|
||||
#endif
|
||||
|
||||
vec2 i_st = rvtx.ST;
|
||||
vec4 i_c = vec4(uvec4(rvtx.RGBA & 0xFFu, (rvtx.RGBA >> 8) & 0xFFu, (rvtx.RGBA >> 16) & 0xFFu, rvtx.RGBA >> 24));
|
||||
vec4 i_c = vec4(uvec4(bitfieldExtract(rvtx.RGBA, 0, 8), bitfieldExtract(rvtx.RGBA, 8, 8),
|
||||
bitfieldExtract(rvtx.RGBA, 16, 8), bitfieldExtract(rvtx.RGBA, 24, 8)));
|
||||
float i_q = rvtx.Q;
|
||||
uvec2 i_p = uvec2(rvtx.XY & 0xFFFFu, rvtx.XY >> 16);
|
||||
uvec2 i_p = uvec2(bitfieldExtract(rvtx.XY, 0, 16), bitfieldExtract(rvtx.XY, 16, 16));
|
||||
uint i_z = rvtx.Z;
|
||||
uvec2 i_uv = uvec2(rvtx.UV & 0xFFFFu, rvtx.UV >> 16);
|
||||
uvec2 i_uv = uvec2(bitfieldExtract(rvtx.UV, 0, 16), bitfieldExtract(rvtx.UV, 16, 16));
|
||||
vec4 i_f = unpackUnorm4x8(rvtx.FOG);
|
||||
|
||||
ProcessedVertex vtx;
|
||||
|
||||
@@ -113,11 +113,12 @@ ProcessedVertex load_vertex(uint index)
|
||||
RawVertex rvtx = vertex_buffer[gl_BaseVertexARB + index];
|
||||
|
||||
vec2 a_st = rvtx.ST;
|
||||
uvec4 a_c = uvec4(rvtx.RGBA & 0xFFu, (rvtx.RGBA >> 8) & 0xFFu, (rvtx.RGBA >> 16) & 0xFFu, rvtx.RGBA >> 24);
|
||||
uvec4 a_c = uvec4(bitfieldExtract(rvtx.RGBA, 0, 8), bitfieldExtract(rvtx.RGBA, 8, 8),
|
||||
bitfieldExtract(rvtx.RGBA, 16, 8), bitfieldExtract(rvtx.RGBA, 24, 8));
|
||||
float a_q = rvtx.Q;
|
||||
uvec2 a_p = uvec2(rvtx.XY & 0xFFFFu, rvtx.XY >> 16);
|
||||
uvec2 a_p = uvec2(bitfieldExtract(rvtx.XY, 0, 16), bitfieldExtract(rvtx.XY, 16, 16));
|
||||
uint a_z = rvtx.Z;
|
||||
uvec2 a_uv = uvec2(rvtx.UV & 0xFFFFu, rvtx.UV >> 16);
|
||||
uvec2 a_uv = uvec2(bitfieldExtract(rvtx.UV, 0, 16), bitfieldExtract(rvtx.UV, 16, 16));
|
||||
vec4 a_f = unpackUnorm4x8(rvtx.FOG);
|
||||
|
||||
ProcessedVertex vtx;
|
||||
|
||||
@@ -52,9 +52,6 @@ if(MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
set(USE_CLANG TRUE)
|
||||
message(STATUS "Building with Clang/LLVM.")
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||
set(USE_ICC TRUE)
|
||||
message(STATUS "Building with Intel's ICC.")
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(USE_GCC TRUE)
|
||||
message(STATUS "Building with GNU GCC")
|
||||
@@ -106,21 +103,13 @@ include(TargetArch)
|
||||
target_architecture(PCSX2_TARGET_ARCHITECTURES)
|
||||
if(${PCSX2_TARGET_ARCHITECTURES} MATCHES "x86_64")
|
||||
message(STATUS "Compiling a ${PCSX2_TARGET_ARCHITECTURES} build on a ${CMAKE_HOST_SYSTEM_PROCESSOR} host.")
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported architecture: ${PCSX2_TARGET_ARCHITECTURES}")
|
||||
endif()
|
||||
|
||||
if(${PCSX2_TARGET_ARCHITECTURES} MATCHES "x86_64")
|
||||
# x86_64 requires -fPIC
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if(NOT DEFINED ARCH_FLAG AND NOT MSVC)
|
||||
if (DISABLE_ADVANCE_SIMD)
|
||||
if (USE_ICC)
|
||||
set(ARCH_FLAG "-msse2 -msse4.1")
|
||||
else()
|
||||
set(ARCH_FLAG "-msse -msse2 -msse4.1 -mfxsr")
|
||||
endif()
|
||||
set(ARCH_FLAG "-msse -msse2 -msse4.1 -mfxsr")
|
||||
else()
|
||||
#set(ARCH_FLAG "-march=native -fabi-version=6")
|
||||
set(ARCH_FLAG "-march=native")
|
||||
@@ -132,9 +121,6 @@ if(${PCSX2_TARGET_ARCHITECTURES} MATCHES "x86_64")
|
||||
set(_ARCH_64 1)
|
||||
set(_M_X86 1)
|
||||
else()
|
||||
# All but i386 requires -fPIC
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
message(FATAL_ERROR "Unsupported architecture: ${PCSX2_TARGET_ARCHITECTURES}")
|
||||
endif()
|
||||
string(REPLACE " " ";" ARCH_FLAG_LIST "${ARCH_FLAG}")
|
||||
@@ -220,24 +206,13 @@ endif()
|
||||
if (MSVC)
|
||||
set(DEFAULT_WARNINGS)
|
||||
else()
|
||||
set(DEFAULT_WARNINGS -Wall -Wextra -Wno-attributes -Wno-unused-function -Wno-unused-parameter -Wno-missing-field-initializers -Wno-format -Wno-format-security)
|
||||
if (NOT USE_ICC)
|
||||
list(APPEND DEFAULT_WARNINGS -Wno-unused-value)
|
||||
endif()
|
||||
set(DEFAULT_WARNINGS -Wall -Wextra -Wno-attributes -Wno-unused-function -Wno-unused-parameter -Wno-missing-field-initializers -Wno-format -Wno-format-security -Wno-unused-value)
|
||||
endif()
|
||||
|
||||
if (USE_GCC)
|
||||
list(APPEND DEFAULT_WARNINGS -Wno-stringop-truncation -Wno-stringop-overflow -Wno-maybe-uninitialized )
|
||||
endif()
|
||||
|
||||
|
||||
# -Wstrict-aliasing=n: to fix one day aliasing issue. n=1/2/3
|
||||
if (USE_ICC)
|
||||
set(AGGRESSIVE_WARNING -Wstrict-aliasing)
|
||||
elseif(NOT MSVC)
|
||||
set(AGGRESSIVE_WARNING -Wstrict-aliasing -Wstrict-overflow=1)
|
||||
endif()
|
||||
|
||||
if (USE_PGO_GENERATE OR USE_PGO_OPTIMIZE)
|
||||
add_compile_options("-fprofile-dir=${CMAKE_SOURCE_DIR}/profile")
|
||||
endif()
|
||||
@@ -264,7 +239,7 @@ if(USE_CLANG AND TIMETRACE)
|
||||
add_compile_options(-ftime-trace)
|
||||
endif()
|
||||
|
||||
set(PCSX2_WARNINGS ${DEFAULT_WARNINGS} ${AGGRESSIVE_WARNING})
|
||||
set(PCSX2_WARNINGS ${DEFAULT_WARNINGS})
|
||||
|
||||
if(DISABLE_BUILD_DATE)
|
||||
message(STATUS "Disabling the inclusion of the binary compile date.")
|
||||
|
||||
@@ -468,10 +468,11 @@ namespace Vulkan
|
||||
SupportsExtension(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, false);
|
||||
m_optional_extensions.vk_ext_line_rasterization =
|
||||
SupportsExtension(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME, false);
|
||||
m_optional_extensions.vk_ext_rasterization_order_attachment_access =
|
||||
SupportsExtension(VK_EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME, false) ||
|
||||
SupportsExtension(VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME, false);
|
||||
m_optional_extensions.vk_khr_driver_properties =
|
||||
SupportsExtension(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, false);
|
||||
m_optional_extensions.vk_arm_rasterization_order_attachment_access =
|
||||
SupportsExtension(VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME, false);
|
||||
m_optional_extensions.vk_khr_fragment_shader_barycentric =
|
||||
SupportsExtension(VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME, false);
|
||||
m_optional_extensions.vk_khr_shader_draw_parameters =
|
||||
@@ -490,7 +491,6 @@ namespace Vulkan
|
||||
|
||||
// Enable the features we use.
|
||||
m_device_features.dualSrcBlend = available_features.dualSrcBlend;
|
||||
m_device_features.geometryShader = available_features.geometryShader;
|
||||
m_device_features.largePoints = available_features.largePoints;
|
||||
m_device_features.wideLines = available_features.wideLines;
|
||||
m_device_features.fragmentStoresAndAtomics = available_features.fragmentStoresAndAtomics;
|
||||
@@ -664,8 +664,8 @@ namespace Vulkan
|
||||
// provoking vertex
|
||||
VkPhysicalDeviceProvokingVertexFeaturesEXT provoking_vertex_feature = {
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT};
|
||||
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM rasterization_order_access_feature = {
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM};
|
||||
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT rasterization_order_access_feature = {
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT};
|
||||
VkPhysicalDeviceLineRasterizationFeaturesEXT line_rasterization_feature = {
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT};
|
||||
|
||||
@@ -679,7 +679,7 @@ namespace Vulkan
|
||||
line_rasterization_feature.bresenhamLines = VK_TRUE;
|
||||
Util::AddPointerToChain(&device_info, &line_rasterization_feature);
|
||||
}
|
||||
if (m_optional_extensions.vk_arm_rasterization_order_attachment_access)
|
||||
if (m_optional_extensions.vk_ext_rasterization_order_attachment_access)
|
||||
{
|
||||
rasterization_order_access_feature.rasterizationOrderColorAttachmentAccess = VK_TRUE;
|
||||
Util::AddPointerToChain(&device_info, &rasterization_order_access_feature);
|
||||
@@ -745,15 +745,15 @@ namespace Vulkan
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT};
|
||||
VkPhysicalDeviceLineRasterizationFeaturesEXT line_rasterization_feature = {
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT};
|
||||
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM rasterization_order_access_feature = {
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM};
|
||||
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT rasterization_order_access_feature = {
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT};
|
||||
|
||||
// add in optional feature structs
|
||||
if (m_optional_extensions.vk_ext_provoking_vertex)
|
||||
Util::AddPointerToChain(&features2, &provoking_vertex_features);
|
||||
if (m_optional_extensions.vk_ext_line_rasterization)
|
||||
Util::AddPointerToChain(&features2, &line_rasterization_feature);
|
||||
if (m_optional_extensions.vk_arm_rasterization_order_attachment_access)
|
||||
if (m_optional_extensions.vk_ext_rasterization_order_attachment_access)
|
||||
Util::AddPointerToChain(&features2, &rasterization_order_access_feature);
|
||||
|
||||
// query
|
||||
@@ -761,7 +761,7 @@ namespace Vulkan
|
||||
|
||||
// confirm we actually support it
|
||||
m_optional_extensions.vk_ext_provoking_vertex &= (provoking_vertex_features.provokingVertexLast == VK_TRUE);
|
||||
m_optional_extensions.vk_arm_rasterization_order_attachment_access &= (rasterization_order_access_feature.rasterizationOrderColorAttachmentAccess == VK_TRUE);
|
||||
m_optional_extensions.vk_ext_rasterization_order_attachment_access &= (rasterization_order_access_feature.rasterizationOrderColorAttachmentAccess == VK_TRUE);
|
||||
m_optional_extensions.vk_ext_line_rasterization &= (line_rasterization_feature.bresenhamLines == VK_TRUE);
|
||||
|
||||
VkPhysicalDeviceProperties2 properties2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
|
||||
@@ -817,8 +817,8 @@ namespace Vulkan
|
||||
m_optional_extensions.vk_ext_line_rasterization ? "supported" : "NOT supported");
|
||||
Console.WriteLn("VK_EXT_calibrated_timestamps is %s",
|
||||
m_optional_extensions.vk_ext_calibrated_timestamps ? "supported" : "NOT supported");
|
||||
Console.WriteLn("VK_ARM_rasterization_order_attachment_access is %s",
|
||||
m_optional_extensions.vk_arm_rasterization_order_attachment_access ? "supported" : "NOT supported");
|
||||
Console.WriteLn("VK_EXT_rasterization_order_attachment_access is %s",
|
||||
m_optional_extensions.vk_ext_rasterization_order_attachment_access ? "supported" : "NOT supported");
|
||||
}
|
||||
|
||||
bool Context::CreateAllocator()
|
||||
@@ -1666,7 +1666,7 @@ namespace Vulkan
|
||||
input_reference.layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
input_reference_ptr = &input_reference;
|
||||
|
||||
if (!g_vulkan_context->GetOptionalExtensions().vk_arm_rasterization_order_attachment_access)
|
||||
if (!g_vulkan_context->GetOptionalExtensions().vk_ext_rasterization_order_attachment_access)
|
||||
{
|
||||
// don't need the framebuffer-local dependency when we have rasterization order attachment access
|
||||
subpass_dependency.srcSubpass = 0;
|
||||
@@ -1699,7 +1699,9 @@ namespace Vulkan
|
||||
}
|
||||
|
||||
const VkSubpassDescriptionFlags subpass_flags =
|
||||
(key.color_feedback_loop && g_vulkan_context->GetOptionalExtensions().vk_arm_rasterization_order_attachment_access) ? VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_ARM : 0;
|
||||
(key.color_feedback_loop && g_vulkan_context->GetOptionalExtensions().vk_ext_rasterization_order_attachment_access) ?
|
||||
VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT :
|
||||
0;
|
||||
const VkSubpassDescription subpass = {subpass_flags, VK_PIPELINE_BIND_POINT_GRAPHICS, input_reference_ptr ? 1u : 0u,
|
||||
input_reference_ptr ? input_reference_ptr : nullptr, color_reference_ptr ? 1u : 0u,
|
||||
color_reference_ptr ? color_reference_ptr : nullptr, nullptr, depth_reference_ptr, 0, nullptr};
|
||||
|
||||
@@ -53,8 +53,8 @@ namespace Vulkan
|
||||
bool vk_ext_memory_budget : 1;
|
||||
bool vk_ext_calibrated_timestamps : 1;
|
||||
bool vk_ext_line_rasterization : 1;
|
||||
bool vk_ext_rasterization_order_attachment_access : 1;
|
||||
bool vk_khr_driver_properties : 1;
|
||||
bool vk_arm_rasterization_order_attachment_access : 1;
|
||||
bool vk_khr_fragment_shader_barycentric : 1;
|
||||
bool vk_khr_shader_draw_parameters : 1;
|
||||
};
|
||||
|
||||
@@ -545,9 +545,7 @@ namespace Vulkan
|
||||
// Determine the dimensions of the swap chain. Values of -1 indicate the size we specify here
|
||||
// determines window size?
|
||||
VkExtent2D size = surface_capabilities.currentExtent;
|
||||
#ifndef ANDROID
|
||||
if (size.width == UINT32_MAX)
|
||||
#endif
|
||||
{
|
||||
size.width = m_window_info.surface_width;
|
||||
size.height = m_window_info.surface_height;
|
||||
@@ -562,6 +560,14 @@ namespace Vulkan
|
||||
if (!(surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR))
|
||||
transform = surface_capabilities.currentTransform;
|
||||
|
||||
VkCompositeAlphaFlagBitsKHR alpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
if (!(surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR))
|
||||
{
|
||||
// If we only support pre-multiplied/post-multiplied... :/
|
||||
if (surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
|
||||
alpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
|
||||
}
|
||||
|
||||
// Select swap chain flags, we only need a colour attachment
|
||||
VkImageUsageFlags image_usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
if (!(surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
|
||||
@@ -577,7 +583,7 @@ namespace Vulkan
|
||||
// Now we can actually create the swap chain
|
||||
VkSwapchainCreateInfoKHR swap_chain_info = {VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, nullptr, 0, m_surface,
|
||||
image_count, m_surface_format.format, m_surface_format.colorSpace, size, 1u, image_usage,
|
||||
VK_SHARING_MODE_EXCLUSIVE, 0, nullptr, transform, VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, m_present_mode,
|
||||
VK_SHARING_MODE_EXCLUSIVE, 0, nullptr, transform, alpha, m_present_mode,
|
||||
VK_TRUE, old_swap_chain};
|
||||
std::array<uint32_t, 2> indices = {{
|
||||
g_vulkan_context->GetGraphicsQueueFamilyIndex(),
|
||||
|
||||
@@ -786,7 +786,7 @@ void MainWindow::setStyleFromSettings()
|
||||
// Alternative dark theme.
|
||||
qApp->setStyle(QStyleFactory::create("Fusion"));
|
||||
|
||||
const QColor gray(192, 192, 192);
|
||||
const QColor gray(150, 150, 150);
|
||||
const QColor royalBlue(29, 41, 81);
|
||||
const QColor darkishBlue(17, 30, 108);
|
||||
const QColor highlight(36, 93, 218);
|
||||
|
||||
@@ -438,16 +438,28 @@
|
||||
<property name="text">
|
||||
<string>&GitHub Repository...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="github">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSupportForums">
|
||||
<property name="text">
|
||||
<string>Support &Forums...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="at">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDiscordServer">
|
||||
<property name="text">
|
||||
<string>&Discord Server...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="discord">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCheckForUpdates">
|
||||
<property name="icon">
|
||||
@@ -471,6 +483,10 @@
|
||||
<property name="text">
|
||||
<string>&About PCSX2...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources/resources.qrc">
|
||||
<normaloff>:/icons/AppIcon.png</normaloff>:/icons/AppIcon.png</iconset>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionChangeDisc">
|
||||
<property name="icon">
|
||||
|
||||
@@ -37,13 +37,19 @@ ControllerGlobalSettingsWidget::ControllerGlobalSettingsWidget(QWidget* parent,
|
||||
#ifdef SDL_BUILD
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableSDLSource, "InputSources", "SDL", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableSDLEnhancedMode, "InputSources", "SDLControllerEnhancedMode", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableSDLRawInput, "InputSources", "SDLRawInput", false);
|
||||
connect(m_ui.enableSDLSource, &QCheckBox::stateChanged, this, &ControllerGlobalSettingsWidget::updateSDLOptionsEnabled);
|
||||
connect(m_ui.ledSettings, &QToolButton::clicked, this, &ControllerGlobalSettingsWidget::ledSettingsClicked);
|
||||
#else
|
||||
m_ui.enableSDLSource->setEnabled(false);
|
||||
m_ui.ledSettings->setEnabled(false);
|
||||
m_ui.enableSDLRawInput->setEnabled(false);
|
||||
#endif
|
||||
|
||||
#if defined(SDL_BUILD) && defined(_WIN32)
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableSDLRawInput, "InputSources", "SDLRawInput", false);
|
||||
#else
|
||||
m_ui.gridLayout_2->removeWidget(m_ui.enableSDLRawInput);
|
||||
m_ui.enableSDLRawInput->deleteLater();
|
||||
m_ui.enableSDLRawInput = nullptr;
|
||||
#endif
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableMouseMapping, "UI", "EnableMouseMapping", false);
|
||||
@@ -62,7 +68,6 @@ ControllerGlobalSettingsWidget::ControllerGlobalSettingsWidget(QWidget* parent,
|
||||
m_ui.mainLayout->removeWidget(m_ui.dinputGroup);
|
||||
m_ui.dinputGroup->deleteLater();
|
||||
m_ui.dinputGroup = nullptr;
|
||||
m_ui.enableSDLRawInput->hide();
|
||||
#endif
|
||||
|
||||
if (dialog->isEditingProfile())
|
||||
@@ -116,7 +121,9 @@ void ControllerGlobalSettingsWidget::updateSDLOptionsEnabled()
|
||||
const bool enabled = m_ui.enableSDLSource->isChecked();
|
||||
m_ui.enableSDLEnhancedMode->setEnabled(enabled);
|
||||
m_ui.ledSettings->setEnabled(enabled);
|
||||
#ifdef _WIN32
|
||||
m_ui.enableSDLRawInput->setEnabled(enabled);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ControllerGlobalSettingsWidget::ledSettingsClicked()
|
||||
|
||||
@@ -662,7 +662,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
||||
dialog->registerWidgetHelp(m_ui.osdShowGSStats, tr("Show Statistics"), tr("Unchecked"),
|
||||
tr("Shows counters for internal graphical utilization, useful for debugging."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.osdShowIndicators, tr("Show Indicators"), tr("Unchecked"),
|
||||
dialog->registerWidgetHelp(m_ui.osdShowIndicators, tr("Show Indicators"), tr("Checked"),
|
||||
tr("Shows OSD icon indicators for emulation states such as Pausing, Turbo, Fast-Forward, and Slow-Motion."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.osdShowSettings, tr("Show Settings"), tr("Unchecked"),
|
||||
|
||||
@@ -5,7 +5,7 @@ IFS="
|
||||
|
||||
printf "<RCC>\n"
|
||||
printf "\t<qresource>\n"
|
||||
for i in $(find . -not -iname '*.sh' -not -iname '*.qrc' -type f | cut -d'/' -f2-99); do
|
||||
for i in $(find . -not -iname '.*' -not -iname '*.sh' -not -iname '*.qrc' -type f | cut -d'/' -f2-99 | sort -f); do
|
||||
printf "\t\t<file>%s</file>\n" "$i"
|
||||
done
|
||||
printf "\t</qresource>\n"
|
||||
|
||||
|
After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 700 B |
|
After Width: | Height: | Size: 1.2 KiB |
@@ -2,6 +2,10 @@
|
||||
Name=Black Icon Theme
|
||||
Comment=Black Icon Theme
|
||||
|
||||
[32]
|
||||
Size=32
|
||||
Type=Fixed
|
||||
|
||||
[svg]
|
||||
Size=64
|
||||
Type=Scalable
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-at" viewBox="0 0 16 16"> <path d="M13.106 7.222c0-2.967-2.249-5.032-5.482-5.032-3.35 0-5.646 2.318-5.646 5.702 0 3.493 2.235 5.708 5.762 5.708.862 0 1.689-.123 2.304-.335v-.862c-.43.199-1.354.328-2.29.328-2.926 0-4.813-1.88-4.813-4.798 0-2.844 1.921-4.881 4.594-4.881 2.735 0 4.608 1.688 4.608 4.156 0 1.682-.554 2.769-1.416 2.769-.492 0-.772-.28-.772-.76V5.206H8.923v.834h-.11c-.266-.595-.881-.964-1.6-.964-1.4 0-2.378 1.162-2.378 2.823 0 1.737.957 2.906 2.379 2.906.8 0 1.415-.39 1.709-1.087h.11c.081.67.703 1.148 1.503 1.148 1.572 0 2.57-1.415 2.57-3.643zm-7.177.704c0-1.197.54-1.907 1.456-1.907.93 0 1.524.738 1.524 1.907S8.308 9.84 7.371 9.84c-.895 0-1.442-.725-1.442-1.914z"/> </svg>
|
||||
|
After Width: | Height: | Size: 939 B |
|
Before Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 695 B |
|
After Width: | Height: | Size: 1.3 KiB |
@@ -2,6 +2,10 @@
|
||||
Name=White Icon Theme
|
||||
Comment=White Icon Theme
|
||||
|
||||
[32]
|
||||
Size=32
|
||||
Type=Fixed
|
||||
|
||||
[svg]
|
||||
Size=64
|
||||
Type=Scalable
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg style="color: white" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-at" viewBox="0 0 16 16"> <path d="M13.106 7.222c0-2.967-2.249-5.032-5.482-5.032-3.35 0-5.646 2.318-5.646 5.702 0 3.493 2.235 5.708 5.762 5.708.862 0 1.689-.123 2.304-.335v-.862c-.43.199-1.354.328-2.29.328-2.926 0-4.813-1.88-4.813-4.798 0-2.844 1.921-4.881 4.594-4.881 2.735 0 4.608 1.688 4.608 4.156 0 1.682-.554 2.769-1.416 2.769-.492 0-.772-.28-.772-.76V5.206H8.923v.834h-.11c-.266-.595-.881-.964-1.6-.964-1.4 0-2.378 1.162-2.378 2.823 0 1.737.957 2.906 2.379 2.906.8 0 1.415-.39 1.709-1.087h.11c.081.67.703 1.148 1.503 1.148 1.572 0 2.57-1.415 2.57-3.643zm-7.177.704c0-1.197.54-1.907 1.456-1.907.93 0 1.524.738 1.524 1.907S8.308 9.84 7.371 9.84c-.895 0-1.442-.725-1.442-1.914z" fill="white"></path> </svg>
|
||||
|
After Width: | Height: | Size: 978 B |
@@ -1,10 +1,13 @@
|
||||
<RCC>
|
||||
<qresource>
|
||||
<file>icons/address-book-new-22.png</file>
|
||||
<file>icons/AppIcon.png</file>
|
||||
<file>icons/applications-system-24.png</file>
|
||||
<file>icons/black/32/discord.png</file>
|
||||
<file>icons/black/32/github.png</file>
|
||||
<file>icons/black/index.theme</file>
|
||||
<file>icons/black/svg/arrow-left-right-line.svg</file>
|
||||
<file>icons/black/svg/artboard-2-line.svg</file>
|
||||
<file>icons/black/svg/at.svg</file>
|
||||
<file>icons/black/svg/book-open-line.svg</file>
|
||||
<file>icons/black/svg/brush-line.svg</file>
|
||||
<file>icons/black/svg/checkbox-multiple-blank-line.svg</file>
|
||||
@@ -56,16 +59,18 @@
|
||||
<file>icons/black/svg/usb-fill.svg</file>
|
||||
<file>icons/black/svg/volume-up-line.svg</file>
|
||||
<file>icons/black/svg/window-2-line.svg</file>
|
||||
<file>icons/discord.png</file>
|
||||
<file>icons/logo.png</file>
|
||||
<file>icons/media-optical-24.png</file>
|
||||
<file>icons/media-optical-gear-24.png</file>
|
||||
<file>icons/media-optical.png</file>
|
||||
<file>icons/QT.png</file>
|
||||
<file>icons/update.png</file>
|
||||
<file>icons/white/32/discord.png</file>
|
||||
<file>icons/white/32/github.png</file>
|
||||
<file>icons/white/index.theme</file>
|
||||
<file>icons/white/svg/arrow-left-right-line.svg</file>
|
||||
<file>icons/white/svg/artboard-2-line.svg</file>
|
||||
<file>icons/white/svg/at.svg</file>
|
||||
<file>icons/white/svg/book-open-line.svg</file>
|
||||
<file>icons/white/svg/brush-line.svg</file>
|
||||
<file>icons/white/svg/checkbox-multiple-blank-line.svg</file>
|
||||
|
||||
@@ -253,7 +253,7 @@ bool InputIsoFile::Open(std::string srcfile, bool testOnly)
|
||||
|
||||
if (!detected)
|
||||
{
|
||||
Console.Error(fmt::format("Unable to identify the ISO image type for '{}'", srcfile));
|
||||
Console.Error(fmt::format("Unable to identify the ISO image type for '{}'", m_filename));
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -566,7 +566,6 @@ set(pcsx2GSHeaders
|
||||
GS/Renderers/Common/GSRenderer.h
|
||||
GS/Renderers/Common/GSTexture.h
|
||||
GS/Renderers/Common/GSVertex.h
|
||||
GS/Renderers/Common/GSVertexList.h
|
||||
GS/Renderers/Common/GSVertexTrace.h
|
||||
GS/Renderers/Null/GSRendererNull.h
|
||||
GS/Renderers/HW/GSHwHack.h
|
||||
|
||||
@@ -38,6 +38,7 @@ SERIAL-12345: # !required! Serial number for the game, this is how games are loo
|
||||
- GIFFIFOHack
|
||||
- GoemonTlbHack
|
||||
- IbitHack
|
||||
- FullVU0SyncHack
|
||||
- VUSyncHack
|
||||
- VUOverflowHack
|
||||
- SoftwareRendererFMVHack
|
||||
@@ -220,6 +221,9 @@ These values are case-sensitive so take care. If you incorrectly specify a Game
|
||||
* `IbitHack`
|
||||
* VU I bit Hack avoid constant recompilation in some games (Scarface The World Is Yours, Crash Tag Team Racing).
|
||||
|
||||
* `FullVU0SyncHack`
|
||||
* Increase the synchronisation points between COP2 and VU0.
|
||||
|
||||
* `VUSyncHack`
|
||||
* Make the VU's run behind/in sync with the EE to fix some timing issues.
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@
|
||||
"VIFFIFOHack",
|
||||
"VuAddSubHack",
|
||||
"VUOverflowHack",
|
||||
"FullVU0SyncHack",
|
||||
"VUSyncHack",
|
||||
"XGKickHack"
|
||||
]
|
||||
|
||||
@@ -3748,6 +3748,8 @@ void FullscreenUI::DrawControllerSettingsPage()
|
||||
DrawToggleSetting(bsi, ICON_FA_WIFI " SDL DualShock 4 / DualSense Enhanced Mode",
|
||||
"Provides vibration and LED control support over Bluetooth.", "InputSources", "SDLControllerEnhancedMode", false,
|
||||
bsi->GetBoolValue("InputSources", "SDL", true), false);
|
||||
#endif
|
||||
#if defined(SDL_BUILD) && defined(_WIN32)
|
||||
DrawToggleSetting(bsi, ICON_FA_COG " SDL Raw Input", "Allow SDL to use raw access to input devices.", "InputSources", "SDLRawInput",
|
||||
false, bsi->GetBoolValue("InputSources", "SDL", true), false);
|
||||
#endif
|
||||
|
||||
@@ -748,12 +748,13 @@ void GSgetStats(std::string& info)
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::format_to(std::back_inserter(info), "{} HW | {} P | {} D | {} DC | {} B | {} RB | {} TC | {} TU",
|
||||
fmt::format_to(std::back_inserter(info), "{} HW | {} P | {} D | {} DC | {} B | {} RP | {} RB | {} TC | {} TU",
|
||||
api_name,
|
||||
(int)pm.Get(GSPerfMon::Prim),
|
||||
(int)pm.Get(GSPerfMon::Draw),
|
||||
(int)std::ceil(pm.Get(GSPerfMon::DrawCalls)),
|
||||
(int)std::ceil(pm.Get(GSPerfMon::Barriers)),
|
||||
(int)std::ceil(pm.Get(GSPerfMon::RenderPasses)),
|
||||
(int)std::ceil(pm.Get(GSPerfMon::Readbacks)),
|
||||
(int)std::ceil(pm.Get(GSPerfMon::TextureCopies)),
|
||||
(int)std::ceil(pm.Get(GSPerfMon::TextureUploads)));
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "GS/GSClut.h"
|
||||
#include "GS/GSExtra.h"
|
||||
#include "GS/GSLocalMemory.h"
|
||||
#include "GS/GSGL.h"
|
||||
#include "GS/Renderers/Common/GSDevice.h"
|
||||
@@ -27,7 +28,7 @@ GSClut::GSClut(GSLocalMemory* mem)
|
||||
static constexpr u32 CLUT_ALLOC_SIZE = 4096 * 2;
|
||||
|
||||
// 1k + 1k for mirrored area simulating wrapping memory
|
||||
m_clut = static_cast<u16*>(_aligned_malloc(CLUT_ALLOC_SIZE, 32));
|
||||
m_clut = static_cast<u16*>(_aligned_malloc(CLUT_ALLOC_SIZE, VECTOR_ALIGNMENT));
|
||||
if (!m_clut)
|
||||
throw std::bad_alloc();
|
||||
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GSVector.h"
|
||||
#include "GS/GSVector.h"
|
||||
#include "pcsx2/Config.h"
|
||||
#include "common/Align.h"
|
||||
|
||||
/// Like `memcmp(&a, &b, sizeof(T)) == 0` but faster
|
||||
template <typename T>
|
||||
@@ -117,6 +118,17 @@ static constexpr u32 MAX_SKIPPED_DUPLICATE_FRAMES = 3;
|
||||
extern void* GSAllocateWrappedMemory(size_t size, size_t repeat);
|
||||
extern void GSFreeWrappedMemory(void* ptr, size_t size, size_t repeat);
|
||||
|
||||
/// We want all allocations and pitches to be aligned to 32-bit, regardless of whether we're
|
||||
/// SSE4 or AVX2, because of multi-ISA.
|
||||
static constexpr u32 VECTOR_ALIGNMENT = 32;
|
||||
|
||||
/// Aligns allocation/pitch size to preferred host size.
|
||||
template<typename T>
|
||||
__fi static T VectorAlign(T value)
|
||||
{
|
||||
return Common::AlignUpPow2(value, VECTOR_ALIGNMENT);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifdef __POSIX__
|
||||
|
||||
@@ -286,7 +286,7 @@ GSPixelOffset* GSLocalMemory::GetPixelOffset(const GIFRegFRAME& FRAME, const GIF
|
||||
return it->second;
|
||||
}
|
||||
|
||||
GSPixelOffset* off = (GSPixelOffset*)_aligned_malloc(sizeof(GSPixelOffset), 32);
|
||||
GSPixelOffset* off = (GSPixelOffset*)_aligned_malloc(sizeof(GSPixelOffset), VECTOR_ALIGNMENT);
|
||||
|
||||
off->hash = hash;
|
||||
off->fbp = fbp;
|
||||
@@ -339,7 +339,7 @@ GSPixelOffset4* GSLocalMemory::GetPixelOffset4(const GIFRegFRAME& FRAME, const G
|
||||
return it->second;
|
||||
}
|
||||
|
||||
GSPixelOffset4* off = (GSPixelOffset4*)_aligned_malloc(sizeof(GSPixelOffset4), 32);
|
||||
GSPixelOffset4* off = (GSPixelOffset4*)_aligned_malloc(sizeof(GSPixelOffset4), VECTOR_ALIGNMENT);
|
||||
|
||||
off->hash = hash;
|
||||
off->fbp = fbp;
|
||||
@@ -544,7 +544,7 @@ void GSLocalMemory::SaveBMP(const std::string& fn, u32 bp, u32 bw, u32 psm, int
|
||||
{
|
||||
int pitch = w * 4;
|
||||
int size = pitch * h;
|
||||
void* bits = _aligned_malloc(size, 32);
|
||||
void* bits = _aligned_malloc(size, VECTOR_ALIGNMENT);
|
||||
|
||||
GIFRegTEX0 TEX0;
|
||||
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include "GSDump.h"
|
||||
#include "GSLzma.h"
|
||||
#include "GS/GSDump.h"
|
||||
#include "GS/GSLzma.h"
|
||||
#include "GS/GSExtra.h"
|
||||
|
||||
using namespace GSDumpTypes;
|
||||
|
||||
@@ -273,8 +274,8 @@ void GSDumpLzma::Initialize()
|
||||
}
|
||||
|
||||
m_buff_size = 1024*1024;
|
||||
m_area = (uint8_t*)_aligned_malloc(m_buff_size, 32);
|
||||
m_inbuf = (uint8_t*)_aligned_malloc(BUFSIZ, 32);
|
||||
m_area = (uint8_t*)_aligned_malloc(m_buff_size, VECTOR_ALIGNMENT);
|
||||
m_inbuf = (uint8_t*)_aligned_malloc(BUFSIZ, VECTOR_ALIGNMENT);
|
||||
m_avail = 0;
|
||||
m_start = 0;
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@ public:
|
||||
Swizzle,
|
||||
Unswizzle,
|
||||
Fillrate,
|
||||
Quad,
|
||||
SyncPoint,
|
||||
Barriers,
|
||||
RenderPasses,
|
||||
CounterLast,
|
||||
|
||||
// Reused counters for HW.
|
||||
|
||||
@@ -2638,31 +2638,31 @@ void GSState::GrowVertexBuffer()
|
||||
{
|
||||
const u32 maxcount = std::max<u32>(m_vertex.maxcount * 3 / 2, 10000);
|
||||
|
||||
GSVertex* vertex = (GSVertex*)_aligned_malloc(sizeof(GSVertex) * maxcount, 32);
|
||||
GSVertex* vertex = static_cast<GSVertex*>(_aligned_malloc(sizeof(GSVertex) * maxcount, 32));
|
||||
// Worst case index list is a list of points with vs expansion, 6 indices per point
|
||||
u32* index = (u32*)_aligned_malloc(sizeof(u32) * maxcount * 6, 32);
|
||||
u16* index = static_cast<u16*>(_aligned_malloc(sizeof(u16) * maxcount * 6, 32));
|
||||
|
||||
if (vertex == NULL || index == NULL)
|
||||
if (!vertex || !index)
|
||||
{
|
||||
const u32 vert_byte_count = sizeof(GSVertex) * maxcount;
|
||||
const u32 idx_byte_count = sizeof(u32) * maxcount * 3;
|
||||
const u32 idx_byte_count = sizeof(u16) * maxcount * 3;
|
||||
|
||||
Console.Error("GS: failed to allocate %zu bytes for verticles and %zu for indices.",
|
||||
Console.Error("GS: failed to allocate %zu bytes for vertices and %zu for indices.",
|
||||
vert_byte_count, idx_byte_count);
|
||||
|
||||
throw GSError();
|
||||
}
|
||||
|
||||
if (m_vertex.buff != NULL)
|
||||
if (m_vertex.buff)
|
||||
{
|
||||
memcpy(vertex, m_vertex.buff, sizeof(GSVertex) * m_vertex.tail);
|
||||
std::memcpy(vertex, m_vertex.buff, sizeof(GSVertex) * m_vertex.tail);
|
||||
|
||||
_aligned_free(m_vertex.buff);
|
||||
}
|
||||
|
||||
if (m_index.buff != NULL)
|
||||
if (m_index.buff)
|
||||
{
|
||||
memcpy(index, m_index.buff, sizeof(u32) * m_index.tail);
|
||||
std::memcpy(index, m_index.buff, sizeof(u16) * m_index.tail);
|
||||
|
||||
_aligned_free(m_index.buff);
|
||||
}
|
||||
@@ -3063,21 +3063,24 @@ static constexpr u32 MaxVerticesForPrim(u32 prim)
|
||||
{
|
||||
switch (prim)
|
||||
{
|
||||
// Four indices per 1 vertex.
|
||||
case GS_POINTLIST:
|
||||
case GS_INVALID:
|
||||
// Needed due to expansion in hardware renderers.
|
||||
|
||||
// Indices are shifted left by 2 to form quads.
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
return (std::numeric_limits<u16>::max() / 4) - 4;
|
||||
|
||||
// Four indices per two vertices.
|
||||
case GS_SPRITE:
|
||||
return (std::numeric_limits<u16>::max() / 2) - 2;
|
||||
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
default:
|
||||
return 0;
|
||||
return (std::numeric_limits<u16>::max() - 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3229,19 +3232,19 @@ __forceinline void GSState::VertexKick(u32 skip)
|
||||
m_backed_up_ctx = m_env.PRIM.CTXT;
|
||||
}
|
||||
|
||||
u32* RESTRICT buff = &m_index.buff[m_index.tail];
|
||||
u16* RESTRICT buff = &m_index.buff[m_index.tail];
|
||||
|
||||
switch (prim)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
buff[0] = head + 0;
|
||||
buff[0] = static_cast<u16>(head + 0);
|
||||
m_vertex.head = head + 1;
|
||||
m_vertex.next = head + 1;
|
||||
m_index.tail += 1;
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
buff[0] = head + (index_swap ? 1 : 0);
|
||||
buff[1] = head + (index_swap ? 0 : 1);
|
||||
buff[0] = static_cast<u16>(head + (index_swap ? 1 : 0));
|
||||
buff[1] = static_cast<u16>(head + (index_swap ? 0 : 1));
|
||||
m_vertex.head = head + 2;
|
||||
m_vertex.next = head + 2;
|
||||
m_index.tail += 2;
|
||||
@@ -3254,16 +3257,16 @@ __forceinline void GSState::VertexKick(u32 skip)
|
||||
head = next;
|
||||
m_vertex.tail = next + 2;
|
||||
}
|
||||
buff[0] = head + (index_swap ? 1 : 0);
|
||||
buff[1] = head + (index_swap ? 0 : 1);
|
||||
buff[0] = static_cast<u16>(head + (index_swap ? 1 : 0));
|
||||
buff[1] = static_cast<u16>(head + (index_swap ? 0 : 1));
|
||||
m_vertex.head = head + 1;
|
||||
m_vertex.next = head + 2;
|
||||
m_index.tail += 2;
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
buff[0] = head + (index_swap ? 2 : 0);
|
||||
buff[1] = head + 1;
|
||||
buff[2] = head + (index_swap ? 0 : 2);
|
||||
buff[0] = static_cast<u16>(head + (index_swap ? 2 : 0));
|
||||
buff[1] = static_cast<u16>(head + 1);
|
||||
buff[2] = static_cast<u16>(head + (index_swap ? 0 : 2));
|
||||
m_vertex.head = head + 3;
|
||||
m_vertex.next = head + 3;
|
||||
m_index.tail += 3;
|
||||
@@ -3277,24 +3280,24 @@ __forceinline void GSState::VertexKick(u32 skip)
|
||||
head = next;
|
||||
m_vertex.tail = next + 3;
|
||||
}
|
||||
buff[0] = head + (index_swap ? 2 : 0);
|
||||
buff[1] = head + 1;
|
||||
buff[2] = head + (index_swap ? 0 : 2);
|
||||
buff[0] = static_cast<u16>(head + (index_swap ? 2 : 0));
|
||||
buff[1] = static_cast<u16>(head + 1);
|
||||
buff[2] = static_cast<u16>(head + (index_swap ? 0 : 2));
|
||||
m_vertex.head = head + 1;
|
||||
m_vertex.next = head + 3;
|
||||
m_index.tail += 3;
|
||||
break;
|
||||
case GS_TRIANGLEFAN:
|
||||
// TODO: remove gaps, next == head && head < tail - 3 || next > head && next < tail - 2 (very rare)
|
||||
buff[0] = index_swap ? (tail - 1) : (head + 0);
|
||||
buff[1] = tail - 2;
|
||||
buff[2] = index_swap ? (head + 0) : (tail - 1);
|
||||
buff[0] = static_cast<u16>(index_swap ? (tail - 1) : (head + 0));
|
||||
buff[1] = static_cast<u16>(tail - 2);
|
||||
buff[2] = static_cast<u16>(index_swap ? (head + 0) : (tail - 1));
|
||||
m_vertex.next = tail;
|
||||
m_index.tail += 3;
|
||||
break;
|
||||
case GS_SPRITE:
|
||||
buff[0] = head + 0;
|
||||
buff[1] = head + 1;
|
||||
buff[0] = static_cast<u16>(head + 0);
|
||||
buff[1] = static_cast<u16>(head + 1);
|
||||
m_vertex.head = head + 2;
|
||||
m_vertex.next = head + 2;
|
||||
m_index.tail += 2;
|
||||
|
||||
@@ -158,7 +158,7 @@ protected:
|
||||
|
||||
struct
|
||||
{
|
||||
u32* buff;
|
||||
u16* buff;
|
||||
u32 tail;
|
||||
} m_index = {};
|
||||
|
||||
|
||||
@@ -28,6 +28,16 @@ class alignas(16) GSVector4i
|
||||
{
|
||||
}
|
||||
|
||||
constexpr GSVector4i(cxpr_init_tag, short s0, short s1, short s2, short s3, short s4, short s5, short s6, short s7)
|
||||
: I16{s0, s1, s2, s3, s4, s5, s6, s7}
|
||||
{
|
||||
}
|
||||
|
||||
constexpr GSVector4i(cxpr_init_tag, char b0, char b1, char b2, char b3, char b4, char b5, char b6, char b7, char b8, char b9, char b10, char b11, char b12, char b13, char b14, char b15)
|
||||
: I8{b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15}
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
union
|
||||
{
|
||||
@@ -62,6 +72,16 @@ public:
|
||||
return GSVector4i(cxpr_init, x, x, x, x);
|
||||
}
|
||||
|
||||
constexpr static GSVector4i cxpr16(short s0, short s1, short s2, short s3, short s4, short s5, short s6, short s7)
|
||||
{
|
||||
return GSVector4i(cxpr_init, s0, s1, s2, s3, s4, s5, s6, s7);
|
||||
}
|
||||
|
||||
constexpr static GSVector4i cxpr8(char b0, char b1, char b2, char b3, char b4, char b5, char b6, char b7, char b8, char b9, char b10, char b11, char b12, char b13, char b14, char b15)
|
||||
{
|
||||
return GSVector4i(cxpr_init, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15);
|
||||
}
|
||||
|
||||
__forceinline GSVector4i(int x, int y, int z, int w)
|
||||
{
|
||||
m = _mm_set_epi32(w, z, y, x);
|
||||
@@ -2001,6 +2021,10 @@ public:
|
||||
return v;
|
||||
}
|
||||
|
||||
__forceinline static GSVector4i broadcast16(u16 value)
|
||||
{
|
||||
return GSVector4i(_mm_set1_epi16(value));
|
||||
}
|
||||
|
||||
__forceinline static GSVector4i zero() { return GSVector4i(_mm_setzero_si128()); }
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "GS/GSGL.h"
|
||||
#include "GS/GS.h"
|
||||
#include "Host.h"
|
||||
#include "common/Align.h"
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include "imgui.h"
|
||||
@@ -165,9 +166,9 @@ std::string GSDevice::GetFullscreenModeString(u32 width, u32 height, float refre
|
||||
|
||||
void GSDevice::GenerateExpansionIndexBuffer(void* buffer)
|
||||
{
|
||||
static constexpr u32 MAX_INDEX = std::numeric_limits<u16>::max();
|
||||
static constexpr u32 MAX_INDEX = EXPAND_BUFFER_SIZE / 6 / sizeof(u16);
|
||||
|
||||
u32* idx_buffer = static_cast<u32*>(buffer);
|
||||
u16* idx_buffer = static_cast<u16*>(buffer);
|
||||
for (u32 i = 0; i < MAX_INDEX; i++)
|
||||
{
|
||||
const u32 base = i * 4;
|
||||
|
||||
@@ -627,7 +627,7 @@ struct alignas(16) GSHWDrawConfig
|
||||
GSTexture* tex; ///< Source texture
|
||||
GSTexture* pal; ///< Palette texture
|
||||
const GSVertex* verts;///< Vertices to draw
|
||||
const u32* indices; ///< Indices to draw
|
||||
const u16* indices; ///< Indices to draw
|
||||
u32 nverts; ///< Number of vertices
|
||||
u32 nindices; ///< Number of indices
|
||||
u32 indices_per_prim; ///< Number of indices that make up one primitive
|
||||
@@ -749,7 +749,7 @@ protected:
|
||||
static constexpr float MAD_SENSITIVITY = 0.08f;
|
||||
static constexpr u32 MAX_POOLED_TEXTURES = 300;
|
||||
static constexpr u32 NUM_CAS_CONSTANTS = 12; // 8 plus src offset x/y, 16 byte alignment
|
||||
static constexpr u32 EXPAND_BUFFER_SIZE = sizeof(u32) * std::numeric_limits<u16>::max() * 6;
|
||||
static constexpr u32 EXPAND_BUFFER_SIZE = sizeof(u16) * 65532 * 6;
|
||||
|
||||
WindowInfo m_window_info;
|
||||
VsyncMode m_vsync_mode = VsyncMode::Off;
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "GSVertexList.h"
|
||||
@@ -1,82 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
template <class Vertex>
|
||||
class GSVertexList
|
||||
{
|
||||
void* m_base;
|
||||
Vertex* m_v[3];
|
||||
int m_count;
|
||||
|
||||
public:
|
||||
GSVertexList()
|
||||
: m_count(0)
|
||||
{
|
||||
m_base = _aligned_malloc(sizeof(Vertex) * std::size(m_v), 32);
|
||||
|
||||
for (size_t i = 0; i < std::size(m_v); i++)
|
||||
{
|
||||
m_v[i] = &((Vertex*)m_base)[i];
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~GSVertexList()
|
||||
{
|
||||
_aligned_free(m_base);
|
||||
}
|
||||
|
||||
void RemoveAll()
|
||||
{
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
__forceinline Vertex& AddTail()
|
||||
{
|
||||
ASSERT(m_count < 3);
|
||||
|
||||
return *m_v[m_count++];
|
||||
}
|
||||
|
||||
__forceinline void RemoveAt(int pos, int keep)
|
||||
{
|
||||
if (keep == 1)
|
||||
{
|
||||
Vertex* tmp = m_v[pos + 0];
|
||||
m_v[pos + 0] = m_v[pos + 1];
|
||||
m_v[pos + 1] = tmp;
|
||||
}
|
||||
else if (keep == 2)
|
||||
{
|
||||
Vertex* tmp = m_v[pos + 0];
|
||||
m_v[pos + 0] = m_v[pos + 1];
|
||||
m_v[pos + 1] = m_v[pos + 2];
|
||||
m_v[pos + 2] = tmp;
|
||||
}
|
||||
|
||||
m_count = pos + keep;
|
||||
}
|
||||
|
||||
__forceinline void GetAt(int i, Vertex& v)
|
||||
{
|
||||
v = *m_v[i];
|
||||
}
|
||||
|
||||
int GetCount()
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
};
|
||||
@@ -24,7 +24,7 @@ GSVertexTrace::GSVertexTrace(const GSState* state, bool provoking_vertex_first)
|
||||
MULTI_ISA_SELECT(GSVertexTracePopulateFunctions)(*this, provoking_vertex_first);
|
||||
}
|
||||
|
||||
void GSVertexTrace::Update(const void* vertex, const u32* index, int v_count, int i_count, GS_PRIM_CLASS primclass)
|
||||
void GSVertexTrace::Update(const void* vertex, const u16* index, int v_count, int i_count, GS_PRIM_CLASS primclass)
|
||||
{
|
||||
if (i_count == 0)
|
||||
return;
|
||||
@@ -43,7 +43,7 @@ void GSVertexTrace::Update(const void* vertex, const u32* index, int v_count, in
|
||||
// that feel big enough.
|
||||
if (!fst && !m_accurate_stq && m_min.t.z > 1e30)
|
||||
{
|
||||
fprintf(stderr, "Vertex Trace: float overflow detected ! min %e max %e\n", m_min.t.z, m_max.t.z);
|
||||
Console.Warning("Vertex Trace: float overflow detected ! min %e max %e", m_min.t.z, m_max.t.z);
|
||||
m_accurate_stq = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
protected:
|
||||
const GSState* m_state;
|
||||
|
||||
typedef void (*FindMinMaxPtr)(GSVertexTrace& vt, const void* vertex, const u32* index, int count);
|
||||
typedef void (*FindMinMaxPtr)(GSVertexTrace& vt, const void* vertex, const u16* index, int count);
|
||||
|
||||
FindMinMaxPtr m_fmm[2][2][2][2][4];
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
public:
|
||||
GSVertexTrace(const GSState* state, bool provoking_vertex_first);
|
||||
|
||||
void Update(const void* vertex, const u32* index, int v_count, int i_count, GS_PRIM_CLASS primclass);
|
||||
void Update(const void* vertex, const u16* index, int v_count, int i_count, GS_PRIM_CLASS primclass);
|
||||
|
||||
bool IsLinear() const { return m_filter.opt_linear; }
|
||||
bool IsRealLinear() const { return m_filter.linear; }
|
||||
|
||||
@@ -22,7 +22,7 @@ class CURRENT_ISA::GSVertexTraceFMM
|
||||
static constexpr GSVector4 s_minmax = GSVector4::cxpr(FLT_MAX, -FLT_MAX, 0.f, 0.f);
|
||||
|
||||
template <GS_PRIM_CLASS primclass, u32 iip, u32 tme, u32 fst, u32 color, bool flat_swapped>
|
||||
static void FindMinMax(GSVertexTrace& vt, const void* vertex, const u32* index, int count);
|
||||
static void FindMinMax(GSVertexTrace& vt, const void* vertex, const u16* index, int count);
|
||||
|
||||
template <GS_PRIM_CLASS primclass, u32 iip, u32 tme, u32 fst, u32 color>
|
||||
static constexpr GSVertexTrace::FindMinMaxPtr GetFMM(bool provoking_vertex_first);
|
||||
@@ -76,7 +76,7 @@ void GSVertexTraceFMM::Populate(GSVertexTrace& vt, bool provoking_vertex_first)
|
||||
}
|
||||
|
||||
template <GS_PRIM_CLASS primclass, u32 iip, u32 tme, u32 fst, u32 color, bool flat_swapped>
|
||||
void GSVertexTraceFMM::FindMinMax(GSVertexTrace& vt, const void* vertex, const u32* index, int count)
|
||||
void GSVertexTraceFMM::FindMinMax(GSVertexTrace& vt, const void* vertex, const u16* index, int count)
|
||||
{
|
||||
const GSDrawingContext* context = vt.m_state->m_context;
|
||||
|
||||
|
||||
@@ -883,7 +883,9 @@ GSDevice::PresentResult GSDevice11::BeginPresent(bool frame_skip)
|
||||
{
|
||||
m_state.dsv->Release();
|
||||
m_state.dsv = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
g_perfmon.Put(GSPerfMon::RenderPasses, 1);
|
||||
|
||||
const GSVector2i size = GetWindowSize();
|
||||
SetViewport(size);
|
||||
@@ -1440,7 +1442,7 @@ void GSDevice11::DoMultiStretchRects(const MultiStretchRect* rects, u32 num_rect
|
||||
const u32 vertex_reserve_size = num_rects * 4;
|
||||
const u32 index_reserve_size = num_rects * 6;
|
||||
GSVertexPT1* verts = static_cast<GSVertexPT1*>(IAMapVertexBuffer(sizeof(GSVertexPT1), vertex_reserve_size));
|
||||
u32* idx = IAMapIndexBuffer(index_reserve_size);
|
||||
u16* idx = IAMapIndexBuffer(index_reserve_size);
|
||||
u32 icount = 0;
|
||||
u32 vcount = 0;
|
||||
for (u32 i = 0; i < num_rects; i++)
|
||||
@@ -1712,7 +1714,6 @@ void GSDevice11::RenderImGui()
|
||||
const UINT vb_stride = sizeof(ImDrawVert);
|
||||
const UINT vb_offset = 0;
|
||||
m_ctx->IASetVertexBuffers(0, 1, m_vb.addressof(), &vb_stride, &vb_offset);
|
||||
m_ctx->IASetIndexBuffer(m_ib.get(), DXGI_FORMAT_R16_UINT, 0);
|
||||
IASetInputLayout(m_imgui.il.get());
|
||||
IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
VSSetShader(m_imgui.vs.get(), m_imgui.vs_cb.get());
|
||||
@@ -1756,16 +1757,8 @@ void GSDevice11::RenderImGui()
|
||||
m_ctx->Unmap(m_vb.get(), 0);
|
||||
}
|
||||
|
||||
// Bit awkward, because this is using 16-bit indices, not 32-bit.
|
||||
static_assert(sizeof(ImDrawIdx) == sizeof(u16));
|
||||
const u32 index_count = static_cast<u32>(cmd_list->IdxBuffer.Size + 1) / 2;
|
||||
u32* index_map = IAMapIndexBuffer(index_count);
|
||||
if (!index_map)
|
||||
continue;
|
||||
|
||||
const u32 index_start = m_index.start * 2;
|
||||
std::memcpy(index_map, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
IAUnmapIndexBuffer(index_count);
|
||||
IASetIndexBuffer(cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size);
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
@@ -1787,14 +1780,13 @@ void GSDevice11::RenderImGui()
|
||||
m_state.ps_sr_views[0] = static_cast<ID3D11ShaderResourceView*>(pcmd->GetTexID());
|
||||
PSUpdateShaderState();
|
||||
|
||||
m_ctx->DrawIndexed(pcmd->ElemCount, index_start + pcmd->IdxOffset, vertex_offset + pcmd->VtxOffset);
|
||||
m_ctx->DrawIndexed(pcmd->ElemCount, m_index.start + pcmd->IdxOffset, vertex_offset + pcmd->VtxOffset);
|
||||
}
|
||||
|
||||
g_perfmon.Put(GSPerfMon::DrawCalls, cmd_list->CmdBuffer.Size);
|
||||
}
|
||||
|
||||
m_ctx->IASetVertexBuffers(0, 1, m_vb.addressof(), &m_state.vb_stride, &vb_offset);
|
||||
m_ctx->IASetIndexBuffer(m_state.index_buffer, DXGI_FORMAT_R32_UINT, 0);
|
||||
}
|
||||
|
||||
void GSDevice11::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, bool datm)
|
||||
@@ -1912,9 +1904,9 @@ bool GSDevice11::IASetExpandVertexBuffer(const void* vertex, u32 stride, u32 cou
|
||||
return true;
|
||||
}
|
||||
|
||||
u32* GSDevice11::IAMapIndexBuffer(u32 count)
|
||||
u16* GSDevice11::IAMapIndexBuffer(u32 count)
|
||||
{
|
||||
if (count > (INDEX_BUFFER_SIZE / sizeof(u32)))
|
||||
if (count > (INDEX_BUFFER_SIZE / sizeof(u16)))
|
||||
return nullptr;
|
||||
|
||||
D3D11_MAP type = D3D11_MAP_WRITE_NO_OVERWRITE;
|
||||
@@ -1922,7 +1914,7 @@ u32* GSDevice11::IAMapIndexBuffer(u32 count)
|
||||
m_index.start = m_ib_pos;
|
||||
m_ib_pos += count;
|
||||
|
||||
if (m_ib_pos > (INDEX_BUFFER_SIZE / sizeof(u32)))
|
||||
if (m_ib_pos > (INDEX_BUFFER_SIZE / sizeof(u16)))
|
||||
{
|
||||
m_index.start = 0;
|
||||
m_ib_pos = count;
|
||||
@@ -1933,7 +1925,7 @@ u32* GSDevice11::IAMapIndexBuffer(u32 count)
|
||||
if (FAILED(m_ctx->Map(m_ib.get(), 0, type, 0, &m)))
|
||||
return nullptr;
|
||||
|
||||
return static_cast<u32*>(m.pData) + m_index.start;
|
||||
return static_cast<u16*>(m.pData) + m_index.start;
|
||||
}
|
||||
|
||||
void GSDevice11::IAUnmapIndexBuffer(u32 count)
|
||||
@@ -1944,11 +1936,11 @@ void GSDevice11::IAUnmapIndexBuffer(u32 count)
|
||||
|
||||
bool GSDevice11::IASetIndexBuffer(const void* index, u32 count)
|
||||
{
|
||||
u32* map = IAMapIndexBuffer(count);
|
||||
u16* map = IAMapIndexBuffer(count);
|
||||
if (!map)
|
||||
return false;
|
||||
|
||||
std::memcpy(map, index, count * sizeof(u32));
|
||||
std::memcpy(map, index, count * sizeof(u16));
|
||||
IAUnmapIndexBuffer(count);
|
||||
IASetIndexBuffer(m_ib.get());
|
||||
return true;
|
||||
@@ -1958,7 +1950,7 @@ void GSDevice11::IASetIndexBuffer(ID3D11Buffer* buffer)
|
||||
{
|
||||
if (m_state.index_buffer != buffer)
|
||||
{
|
||||
m_ctx->IASetIndexBuffer(buffer, DXGI_FORMAT_R32_UINT, 0);
|
||||
m_ctx->IASetIndexBuffer(buffer, DXGI_FORMAT_R16_UINT, 0);
|
||||
m_state.index_buffer = buffer;
|
||||
}
|
||||
}
|
||||
@@ -2073,6 +2065,8 @@ void GSDevice11::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector
|
||||
if (ds) dsv = *(GSTexture11*)ds;
|
||||
|
||||
const bool changed = (m_state.rt_view != rtv || m_state.dsv != dsv);
|
||||
g_perfmon.Put(GSPerfMon::RenderPasses, static_cast<double>(changed));
|
||||
|
||||
if (m_state.rt_view != rtv)
|
||||
{
|
||||
if (m_state.rt_view)
|
||||
|
||||
@@ -343,7 +343,7 @@ public:
|
||||
bool IASetVertexBuffer(const void* vertex, u32 stride, u32 count);
|
||||
bool IASetExpandVertexBuffer(const void* vertex, u32 stride, u32 count);
|
||||
|
||||
u32* IAMapIndexBuffer(u32 count);
|
||||
u16* IAMapIndexBuffer(u32 count);
|
||||
void IAUnmapIndexBuffer(u32 count);
|
||||
bool IASetIndexBuffer(const void* index, u32 count);
|
||||
void IASetIndexBuffer(ID3D11Buffer* buffer);
|
||||
|
||||
@@ -538,6 +538,7 @@ GSDevice::PresentResult GSDevice12::BeginPresent(bool frame_skip)
|
||||
swap_chain_buf.TransitionToState(cmdlist, D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
cmdlist->ClearRenderTargetView(swap_chain_buf.GetWriteDescriptor(), clear_color.data(), 0, nullptr);
|
||||
cmdlist->OMSetRenderTargets(1, &swap_chain_buf.GetWriteDescriptor().cpu_handle, FALSE, nullptr);
|
||||
g_perfmon.Put(GSPerfMon::RenderPasses, 1);
|
||||
|
||||
const D3D12_VIEWPORT vp{0.0f, 0.0f, static_cast<float>(m_window_info.surface_width),
|
||||
static_cast<float>(m_window_info.surface_height), 0.0f, 1.0f};
|
||||
@@ -949,13 +950,13 @@ void GSDevice12::DoMultiStretchRects(
|
||||
{
|
||||
// Set up vertices first.
|
||||
const u32 vertex_reserve_size = num_rects * 4 * sizeof(GSVertexPT1);
|
||||
const u32 index_reserve_size = num_rects * 6 * sizeof(u32);
|
||||
const u32 index_reserve_size = num_rects * 6 * sizeof(u16);
|
||||
if (!m_vertex_stream_buffer.ReserveMemory(vertex_reserve_size, sizeof(GSVertexPT1)) ||
|
||||
!m_index_stream_buffer.ReserveMemory(index_reserve_size, sizeof(u32)))
|
||||
!m_index_stream_buffer.ReserveMemory(index_reserve_size, sizeof(u16)))
|
||||
{
|
||||
ExecuteCommandListAndRestartRenderPass(false, "Uploading bytes to vertex buffer");
|
||||
if (!m_vertex_stream_buffer.ReserveMemory(vertex_reserve_size, sizeof(GSVertexPT1)) ||
|
||||
!m_index_stream_buffer.ReserveMemory(index_reserve_size, sizeof(u32)))
|
||||
!m_index_stream_buffer.ReserveMemory(index_reserve_size, sizeof(u16)))
|
||||
{
|
||||
pxFailRel("Failed to reserve space for vertices");
|
||||
}
|
||||
@@ -965,7 +966,7 @@ void GSDevice12::DoMultiStretchRects(
|
||||
// Don't use primitive restart here, it ends up slower on some drivers.
|
||||
const GSVector2 ds(static_cast<float>(dTex->GetWidth()), static_cast<float>(dTex->GetHeight()));
|
||||
GSVertexPT1* verts = reinterpret_cast<GSVertexPT1*>(m_vertex_stream_buffer.GetCurrentHostPointer());
|
||||
u32* idx = reinterpret_cast<u32*>(m_index_stream_buffer.GetCurrentHostPointer());
|
||||
u16* idx = reinterpret_cast<u16*>(m_index_stream_buffer.GetCurrentHostPointer());
|
||||
u32 icount = 0;
|
||||
u32 vcount = 0;
|
||||
for (u32 i = 0; i < num_rects; i++)
|
||||
@@ -996,12 +997,12 @@ void GSDevice12::DoMultiStretchRects(
|
||||
|
||||
m_vertex.start = m_vertex_stream_buffer.GetCurrentOffset() / sizeof(GSVertexPT1);
|
||||
m_vertex.count = vcount;
|
||||
m_index.start = m_index_stream_buffer.GetCurrentOffset() / sizeof(u32);
|
||||
m_index.start = m_index_stream_buffer.GetCurrentOffset() / sizeof(u16);
|
||||
m_index.count = icount;
|
||||
m_vertex_stream_buffer.CommitMemory(vcount * sizeof(GSVertexPT1));
|
||||
m_index_stream_buffer.CommitMemory(icount * sizeof(u32));
|
||||
m_index_stream_buffer.CommitMemory(icount * sizeof(u16));
|
||||
SetVertexBuffer(m_vertex_stream_buffer.GetGPUPointer(), m_vertex_stream_buffer.GetSize(), sizeof(GSVertexPT1));
|
||||
SetIndexBuffer(m_index_stream_buffer.GetGPUPointer(), m_index_stream_buffer.GetSize(), DXGI_FORMAT_R32_UINT);
|
||||
SetIndexBuffer(m_index_stream_buffer.GetGPUPointer(), m_index_stream_buffer.GetSize(), DXGI_FORMAT_R16_UINT);
|
||||
|
||||
// Even though we're batching, a cmdbuffer submit could've messed this up.
|
||||
const GSVector4i rc(dTex->GetRect());
|
||||
@@ -1422,22 +1423,10 @@ void GSDevice12::RenderImGui()
|
||||
m_vertex_stream_buffer.CommitMemory(size);
|
||||
}
|
||||
|
||||
u32 index_offset;
|
||||
{
|
||||
const u32 size = sizeof(ImDrawIdx) * static_cast<u32>(cmd_list->IdxBuffer.Size);
|
||||
if (!m_index_stream_buffer.ReserveMemory(size, sizeof(ImDrawIdx)))
|
||||
{
|
||||
Console.Warning("Skipping ImGui draw because of no vertex buffer space");
|
||||
return;
|
||||
}
|
||||
|
||||
index_offset = m_index_stream_buffer.GetCurrentOffset() / sizeof(ImDrawIdx);
|
||||
std::memcpy(m_index_stream_buffer.GetCurrentHostPointer(), cmd_list->IdxBuffer.Data, size);
|
||||
m_index_stream_buffer.CommitMemory(size);
|
||||
}
|
||||
|
||||
SetVertexBuffer(m_vertex_stream_buffer.GetGPUPointer(), m_vertex_stream_buffer.GetSize(), sizeof(ImDrawVert));
|
||||
SetIndexBuffer(m_index_stream_buffer.GetGPUPointer(), m_index_stream_buffer.GetSize(), DXGI_FORMAT_R16_UINT);
|
||||
|
||||
static_assert(sizeof(ImDrawIdx) == sizeof(u16));
|
||||
IASetIndexBuffer(cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size);
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
@@ -1468,7 +1457,7 @@ void GSDevice12::RenderImGui()
|
||||
if (ApplyUtilityState())
|
||||
{
|
||||
g_d3d12_context->GetCommandList()->DrawIndexedInstanced(
|
||||
pcmd->ElemCount, 1, index_offset + pcmd->IdxOffset, vertex_offset + pcmd->VtxOffset, 0);
|
||||
pcmd->ElemCount, 1, m_index.start + pcmd->IdxOffset, vertex_offset + pcmd->VtxOffset, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1536,17 +1525,17 @@ void GSDevice12::IASetVertexBuffer(const void* vertex, size_t stride, size_t cou
|
||||
|
||||
void GSDevice12::IASetIndexBuffer(const void* index, size_t count)
|
||||
{
|
||||
const u32 size = sizeof(u32) * static_cast<u32>(count);
|
||||
if (!m_index_stream_buffer.ReserveMemory(size, sizeof(u32)))
|
||||
const u32 size = sizeof(u16) * static_cast<u32>(count);
|
||||
if (!m_index_stream_buffer.ReserveMemory(size, sizeof(u16)))
|
||||
{
|
||||
ExecuteCommandListAndRestartRenderPass(false, "Uploading bytes to index buffer");
|
||||
if (!m_index_stream_buffer.ReserveMemory(size, sizeof(u32)))
|
||||
if (!m_index_stream_buffer.ReserveMemory(size, sizeof(u16)))
|
||||
pxFailRel("Failed to reserve space for vertices");
|
||||
}
|
||||
|
||||
m_index.start = m_index_stream_buffer.GetCurrentOffset() / sizeof(u32);
|
||||
m_index.start = m_index_stream_buffer.GetCurrentOffset() / sizeof(u16);
|
||||
m_index.count = count;
|
||||
SetIndexBuffer(m_index_stream_buffer.GetGPUPointer(), m_index_stream_buffer.GetSize(), DXGI_FORMAT_R32_UINT);
|
||||
SetIndexBuffer(m_index_stream_buffer.GetGPUPointer(), m_index_stream_buffer.GetSize(), DXGI_FORMAT_R16_UINT);
|
||||
|
||||
std::memcpy(m_index_stream_buffer.GetCurrentHostPointer(), index, size);
|
||||
m_index_stream_buffer.CommitMemory(size);
|
||||
@@ -2758,11 +2747,15 @@ void GSDevice12::EndRenderPass()
|
||||
if (!m_in_render_pass)
|
||||
return;
|
||||
|
||||
g_d3d12_context->GetCommandList()->EndRenderPass();
|
||||
m_in_render_pass = false;
|
||||
|
||||
// to render again, we need to reset OM
|
||||
m_dirty_flags |= DIRTY_FLAG_RENDER_TARGET;
|
||||
|
||||
g_perfmon.Put(GSPerfMon::RenderPasses, 1);
|
||||
|
||||
g_d3d12_context->GetCommandList()->EndRenderPass();
|
||||
|
||||
}
|
||||
|
||||
void GSDevice12::SetViewport(const D3D12_VIEWPORT& viewport)
|
||||
@@ -3212,8 +3205,20 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
|
||||
// avoid restarting the render pass just to switch from rt+depth to rt and vice versa
|
||||
if (m_in_render_pass && !hdr_rt && !draw_ds && m_current_depth_target && m_current_render_target == draw_rt &&
|
||||
config.tex != m_current_depth_target && m_current_depth_target->GetSize() == draw_rt->GetSize())
|
||||
if (m_in_render_pass && (m_current_render_target == draw_rt || m_current_depth_target == draw_ds))
|
||||
{
|
||||
// avoid restarting the render pass just to switch from rt+depth to rt and vice versa
|
||||
// keep the depth even if doing HDR draws, because the next draw will probably re-enable depth
|
||||
if (!draw_rt && m_current_render_target && config.tex != m_current_render_target &&
|
||||
m_current_render_target->GetSize() == draw_ds->GetSize())
|
||||
{
|
||||
draw_rt = m_current_render_target;
|
||||
m_pipeline_selector.rt = true;
|
||||
m_pipeline_selector.cms.wrgba = 0;
|
||||
}
|
||||
}
|
||||
else if (!draw_ds && m_current_depth_target && config.tex != m_current_depth_target &&
|
||||
m_current_depth_target->GetSize() == draw_rt->GetSize())
|
||||
{
|
||||
draw_ds = m_current_depth_target;
|
||||
m_pipeline_selector.ds = true;
|
||||
@@ -3353,7 +3358,7 @@ void GSDevice12::UploadHWDrawVerticesAndIndices(const GSHWDrawConfig& config)
|
||||
{
|
||||
m_index.start = 0;
|
||||
m_index.count = config.nindices;
|
||||
SetIndexBuffer(m_expand_index_buffer->GetGPUVirtualAddress(), EXPAND_BUFFER_SIZE, DXGI_FORMAT_R32_UINT);
|
||||
SetIndexBuffer(m_expand_index_buffer->GetGPUVirtualAddress(), EXPAND_BUFFER_SIZE, DXGI_FORMAT_R16_UINT);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -297,7 +297,7 @@ bool GSHwHack::GSC_BlackAndBurnoutSky(GSRendererHW& r, int& skip)
|
||||
if (RPRIM->PRIM == GS_SPRITE && !RPRIM->IIP && RPRIM->TME && !RPRIM->FGE && RPRIM->ABE && !RPRIM->AA1 && !RPRIM->FST && !RPRIM->FIX &&
|
||||
ALPHA.A == ALPHA.B && ALPHA.D == 0 && FRAME.PSM == PSMCT32 && TEX0.CPSM == PSMCT32 && TEX0.TCC && !TEX0.TFX && !TEX0.CSM)
|
||||
{
|
||||
if (TEX0.TBW == 16 && TEX0.TW == 10 && TEX0.PSM == PSMT8 && TEX0.TH == 8 && FRAME.FBW == 16)
|
||||
if (TEX0.TBW == 16 && TEX0.TW == 10 && TEX0.PSM == PSMT8 && TEX0.TH >= 7 && FRAME.FBW == 16)
|
||||
{
|
||||
// Readback clouds being rendered during level loading.
|
||||
// Later the alpha channel from the 32 bit frame buffer is used as an 8 bit indexed texture to draw
|
||||
|
||||
@@ -258,14 +258,10 @@ void GSRendererHW::Lines2Sprites()
|
||||
int i = static_cast<int>(count) * 2 - 4;
|
||||
GSVertex* s = &m_vertex.buff[count - 2];
|
||||
GSVertex* q = &m_vertex.buff[count * 2 - 4];
|
||||
u32* RESTRICT index = &m_index.buff[count * 3 - 6];
|
||||
u16* RESTRICT index = &m_index.buff[count * 3 - 6];
|
||||
|
||||
alignas(16) static constexpr std::array<int, 8> tri_normal_indices = {{0, 1, 2, 1, 2, 3}};
|
||||
alignas(16) static constexpr std::array<int, 8> tri_swapped_indices = {{0, 1, 2, 1, 2, 3}};
|
||||
const bool index_swap = !g_gs_device->Features().provoking_vertex_last;
|
||||
const int* tri_indices = index_swap ? tri_swapped_indices.data() : tri_normal_indices.data();
|
||||
const GSVector4i indices_low(GSVector4i::load<true>(tri_indices));
|
||||
const GSVector4i indices_high(GSVector4i::loadl(tri_indices + 4));
|
||||
// Sprites are flat shaded, so the provoking vertex doesn't matter here.
|
||||
constexpr GSVector4i indices = GSVector4i::cxpr16(0, 1, 2, 1, 2, 3, 0, 0);
|
||||
|
||||
for (; i >= 0; i -= 4, s -= 2, q -= 4, index -= 6)
|
||||
{
|
||||
@@ -310,9 +306,10 @@ void GSRendererHW::Lines2Sprites()
|
||||
q[1] = v0;
|
||||
q[2] = v1;
|
||||
|
||||
const GSVector4i i_splat(i);
|
||||
GSVector4i::store<false>(index, i_splat + indices_low);
|
||||
GSVector4i::storel(index + 4, i_splat + indices_high);
|
||||
const GSVector4i this_indices = GSVector4i::broadcast16(i).add16(indices);
|
||||
const int high = this_indices.extract32<2>();
|
||||
GSVector4i::storel(index, this_indices);
|
||||
std::memcpy(&index[4], &high, sizeof(high));
|
||||
}
|
||||
|
||||
m_vertex.head = m_vertex.tail = m_vertex.next = count * 2;
|
||||
@@ -322,26 +319,30 @@ void GSRendererHW::Lines2Sprites()
|
||||
|
||||
void GSRendererHW::ExpandLineIndices()
|
||||
{
|
||||
const u32 process_count = (m_index.tail + 3) / 4 * 4;
|
||||
const u32 process_count = (m_index.tail + 7) / 8 * 8;
|
||||
const u32 expansion_factor = 3;
|
||||
m_index.tail *= expansion_factor;
|
||||
GSVector4i* end = reinterpret_cast<GSVector4i*>(m_index.buff);
|
||||
GSVector4i* read = reinterpret_cast<GSVector4i*>(m_index.buff + process_count);
|
||||
GSVector4i* write = reinterpret_cast<GSVector4i*>(m_index.buff + process_count * expansion_factor);
|
||||
|
||||
constexpr GSVector4i low0 = GSVector4i::cxpr(0, 1, 2, 1);
|
||||
constexpr GSVector4i low1 = GSVector4i::cxpr(2, 3, 0, 1);
|
||||
constexpr GSVector4i low2 = GSVector4i::cxpr(2, 1, 2, 3);
|
||||
constexpr GSVector4i mask0 = GSVector4i::cxpr8(0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 2, 3, 4, 5, 4, 5);
|
||||
constexpr GSVector4i mask1 = GSVector4i::cxpr8(6, 7, 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 10, 11, 8, 9);
|
||||
constexpr GSVector4i mask2 = GSVector4i::cxpr8(10, 11, 10, 11, 12, 13, 12, 13, 14, 15, 12, 13, 14, 15, 14, 15);
|
||||
|
||||
constexpr GSVector4i low0 = GSVector4i::cxpr16(0, 1, 2, 1, 2, 3, 0, 1);
|
||||
constexpr GSVector4i low1 = GSVector4i::cxpr16(2, 1, 2, 3, 0, 1, 2, 1);
|
||||
constexpr GSVector4i low2 = GSVector4i::cxpr16(2, 3, 0, 1, 2, 1, 2, 3);
|
||||
|
||||
while (read > end)
|
||||
{
|
||||
read -= 1;
|
||||
write -= expansion_factor;
|
||||
|
||||
const GSVector4i in = read->sll32(2);
|
||||
write[0] = in.xxyx() | low0;
|
||||
write[1] = in.yyzz() | low1;
|
||||
write[2] = in.wzww() | low2;
|
||||
const GSVector4i in = read->sll16(2);
|
||||
write[0] = in.shuffle8(mask0) | low0;
|
||||
write[1] = in.shuffle8(mask1) | low1;
|
||||
write[2] = in.shuffle8(mask2) | low2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1434,7 +1435,7 @@ void GSRendererHW::Draw()
|
||||
#endif
|
||||
}
|
||||
|
||||
GL_PUSH("HW Draw %d", s_n);
|
||||
GL_PUSH("HW Draw %d (Context %u)", s_n, PRIM->CTXT);
|
||||
|
||||
// When the format is 24bit (Z or C), DATE ceases to function.
|
||||
// It was believed that in 24bit mode all pixels pass because alpha doesn't exist
|
||||
@@ -3606,11 +3607,11 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
|
||||
const u8 wms = EffectiveClamp(m_cached_ctx.CLAMP.WMS, !tex->m_target && (source_region.HasX() || redundant_wms));
|
||||
const u8 wmt = EffectiveClamp(m_cached_ctx.CLAMP.WMT, !tex->m_target && (source_region.HasY() || redundant_wmt));
|
||||
const bool complex_wms_wmt = !!((wms | wmt) & 2) || target_region;
|
||||
GL_CACHE("WMS: %s [%s%s] WMT: %s [%s%s] Complex: %d TargetRegion: %d MINU: %d MAXU: %d MINV: %d MAXV: %d",
|
||||
clamp_modes[m_cached_ctx.CLAMP.WMS], redundant_wms ? "redundant," : "", clamp_modes[wms],
|
||||
clamp_modes[m_cached_ctx.CLAMP.WMT], redundant_wmt ? "redundant," : "", clamp_modes[wmt],
|
||||
complex_wms_wmt, target_region,
|
||||
m_cached_ctx.CLAMP.MINU, m_cached_ctx.CLAMP.MAXU, m_cached_ctx.CLAMP.MINV, m_cached_ctx.CLAMP.MAXV);
|
||||
GL_CACHE("FST: %s WMS: %s [%s%s] WMT: %s [%s%s] Complex: %d TargetRegion: %d MINU: %d MAXU: %d MINV: %d MAXV: %d",
|
||||
PRIM->FST ? "UV" : "STQ", clamp_modes[m_cached_ctx.CLAMP.WMS], redundant_wms ? "redundant," : "",
|
||||
clamp_modes[wms], clamp_modes[m_cached_ctx.CLAMP.WMT], redundant_wmt ? "redundant," : "", clamp_modes[wmt],
|
||||
complex_wms_wmt, target_region, m_cached_ctx.CLAMP.MINU, m_cached_ctx.CLAMP.MAXU, m_cached_ctx.CLAMP.MINV,
|
||||
m_cached_ctx.CLAMP.MAXV);
|
||||
|
||||
const bool need_mipmap = IsMipMapDraw();
|
||||
const bool shader_emulated_sampler = tex->m_palette || (tex->m_target && !m_conf.ps.shuffle && cpsm.fmt != 0) ||
|
||||
@@ -4934,16 +4935,15 @@ void GSRendererHW::OI_DoubleHalfClear(GSTextureCache::Target*& rt, GSTextureCach
|
||||
clear_depth ? "depth" : "target", base << 5, half << 5, w_pages, h_pages, m_cached_ctx.FRAME.FBW, color);
|
||||
|
||||
// If some of the channels are masked, we need to keep them.
|
||||
if (m_cached_ctx.FRAME.FBMSK != 0)
|
||||
if (!clear_depth && m_cached_ctx.FRAME.FBMSK != 0)
|
||||
{
|
||||
GSTexture* tex = nullptr;
|
||||
GSTextureCache::Target* target = clear_depth ? ds : rt;
|
||||
const GSVector2 size = GSVector2(static_cast<float>(target->GetUnscaledWidth()) * target->m_scale, static_cast<float>(target->GetUnscaledHeight()) * target->m_scale);
|
||||
pxAssert(!target->m_texture->IsDepthStencil());
|
||||
try
|
||||
{
|
||||
tex = target->m_texture->IsDepthStencil() ?
|
||||
g_gs_device->CreateDepthStencil(size.x, size.y, target->m_texture->GetFormat(), true) :
|
||||
g_gs_device->CreateRenderTarget(size.x, size.y, target->m_texture->GetFormat(), true);
|
||||
tex = g_gs_device->CreateRenderTarget(size.x, size.y, target->m_texture->GetFormat(), false);
|
||||
}
|
||||
catch (const std::bad_alloc&)
|
||||
{
|
||||
|
||||
@@ -40,7 +40,8 @@ GSTextureCache::GSTextureCache()
|
||||
// In theory 4MB is enough but 9MB is safer for overflow (8MB
|
||||
// isn't enough in custom resolution)
|
||||
// Test: onimusha 3 PAL 60Hz
|
||||
s_unswizzle_buffer = (u8*)_aligned_malloc(9 * 1024 * 1024, 32);
|
||||
s_unswizzle_buffer = (u8*)_aligned_malloc(9 * 1024 * 1024, VECTOR_ALIGNMENT);
|
||||
pxAssertRel(s_unswizzle_buffer, "Failed to allocate unswizzle buffer");
|
||||
|
||||
m_surface_offset_cache.reserve(S_SURFACE_OFFSET_CACHE_MAX_SIZE);
|
||||
}
|
||||
@@ -2576,7 +2577,7 @@ bool GSTextureCache::ShuffleMove(u32 BP, u32 BW, u32 PSM, int sx, int sy, int dx
|
||||
|
||||
#undef V
|
||||
|
||||
static constexpr u32 indices[6] = { 0, 1, 2, 2, 1, 3 };
|
||||
static constexpr u16 indices[6] = { 0, 1, 2, 2, 1, 3 };
|
||||
|
||||
// If we ever do this sort of thing somewhere else, extract this to a helper function.
|
||||
GSHWDrawConfig config;
|
||||
@@ -3605,6 +3606,7 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0
|
||||
if (it != m_hash_cache.end())
|
||||
{
|
||||
// super easy, cache hit. remove paltex if it's a replacement texture.
|
||||
GL_CACHE("HC Hit: %" PRIx64 " %" PRIx64 " R-%" PRIx64, key.TEX0Hash, key.CLUTHash, key.region.bits);
|
||||
HashCacheEntry* entry = &it->second;
|
||||
paltex &= (entry->texture->GetFormat() == GSTexture::Format::UNorm8);
|
||||
entry->refcount++;
|
||||
@@ -3612,6 +3614,8 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0
|
||||
}
|
||||
|
||||
// cache miss.
|
||||
GL_CACHE("HC Miss: %" PRIx64 " %" PRIx64 " R-%" PRIx64, key.TEX0Hash, key.CLUTHash, key.region.bits);
|
||||
|
||||
// check for a replacement texture with the full clut key
|
||||
if (replace)
|
||||
{
|
||||
@@ -4154,7 +4158,7 @@ void GSTextureCache::Source::UpdateLayer(const GIFRegTEX0& TEX0, const GSVector4
|
||||
void GSTextureCache::Source::Write(const GSVector4i& r, int layer, const GSOffset& off)
|
||||
{
|
||||
if (!m_write.rect)
|
||||
m_write.rect = static_cast<GSVector4i*>(_aligned_malloc(3 * sizeof(GSVector4i), 32));
|
||||
m_write.rect = static_cast<GSVector4i*>(_aligned_malloc(3 * sizeof(GSVector4i), 16));
|
||||
|
||||
m_write.rect[m_write.count++] = r;
|
||||
|
||||
@@ -4214,6 +4218,8 @@ void GSTextureCache::Source::Flush(u32 count, int layer, const GSOffset& off)
|
||||
rtx = psm.rtxP;
|
||||
}
|
||||
|
||||
pitch = VectorAlign(pitch);
|
||||
|
||||
for (u32 i = 0; i < count; i++)
|
||||
{
|
||||
const GSVector4i r(m_write.rect[i]);
|
||||
@@ -4385,7 +4391,7 @@ void GSTextureCache::Target::Update(bool reset_age)
|
||||
}
|
||||
else
|
||||
{
|
||||
const int pitch = Common::AlignUpPow2(r.width() * sizeof(u32), 32);
|
||||
const int pitch = VectorAlign(r.width() * sizeof(u32));
|
||||
g_gs_renderer->m_mem.ReadTexture(off, r, s_unswizzle_buffer, pitch, TEXA);
|
||||
|
||||
t->Update(t_r, s_unswizzle_buffer, pitch);
|
||||
@@ -5127,13 +5133,13 @@ GSTextureCache::SourceRegion GSTextureCache::SourceRegion::AdjustForMipmap(u32 l
|
||||
if (HasX())
|
||||
{
|
||||
const u32 new_minx = GetMinX() >> level;
|
||||
const u32 new_maxx = std::max<u32>(GetMaxX() >> level, new_minx + 1);
|
||||
const u32 new_maxx = new_minx + std::max(GetWidth() >> level, 1u);
|
||||
ret.SetX(new_minx, new_maxx);
|
||||
}
|
||||
if (HasY())
|
||||
{
|
||||
const u32 new_miny = GetMinY() >> level;
|
||||
const u32 new_maxy = std::max<u32>(GetMaxY() >> level, new_miny + 1);
|
||||
const u32 new_maxy = new_miny + std::max(GetHeight() >> level, 1u);
|
||||
ret.SetY(new_miny, new_maxy);
|
||||
}
|
||||
return ret;
|
||||
@@ -5241,7 +5247,7 @@ static void HashTextureLevel(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, GST
|
||||
{
|
||||
// Expand texture indices. Align to 32 bytes for AVX2.
|
||||
const bool palette = (psm.pal > 0);
|
||||
const u32 pitch = Common::AlignUpPow2(static_cast<u32>(block_rect.z) << (palette ? 0 : 2), 32);
|
||||
const u32 pitch = VectorAlign(static_cast<u32>(block_rect.z) << (palette ? 0 : 2));
|
||||
const u32 row_size = static_cast<u32>(tw) << (palette ? 0 : 2);
|
||||
const GSLocalMemory::readTexture rtx = palette ? psm.rtxP : psm.rtx;
|
||||
|
||||
@@ -5317,8 +5323,7 @@ void GSTextureCache::PreloadTexture(const GIFRegTEX0& TEX0, const GIFRegTEXA& TE
|
||||
}
|
||||
else
|
||||
{
|
||||
// Align pitch to 32 bytes for AVX2 if we're going through the temp buffer path.
|
||||
pitch = Common::AlignUpPow2(pitch, 32);
|
||||
pitch = VectorAlign(pitch);
|
||||
|
||||
u8* buff = s_unswizzle_buffer;
|
||||
rtx(mem, off, block_rect, buff, pitch, TEXA);
|
||||
|
||||
@@ -209,6 +209,7 @@ std::optional<TextureName> GSTextureReplacements::ParseReplacementName(const std
|
||||
&ret.bits, &extension_dot) == 4 &&
|
||||
extension_dot == '.')
|
||||
{
|
||||
ret.CLUTHash = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -225,6 +226,7 @@ std::optional<TextureName> GSTextureReplacements::ParseReplacementName(const std
|
||||
3 &&
|
||||
extension_dot == '.')
|
||||
{
|
||||
ret.CLUTHash = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -371,6 +371,7 @@ void GSDeviceMTL::EndRenderPass()
|
||||
if (m_current_render.encoder)
|
||||
{
|
||||
EndDebugGroup(m_current_render.encoder);
|
||||
g_perfmon.Put(GSPerfMon::RenderPasses, 1);
|
||||
if (m_spin_timer)
|
||||
[m_current_render.encoder updateFence:m_spin_fence afterStages:MTLRenderStageFragment];
|
||||
[m_current_render.encoder endEncoding];
|
||||
@@ -1240,53 +1241,51 @@ static bool s_capture_next = false;
|
||||
|
||||
GSDevice::PresentResult GSDeviceMTL::BeginPresent(bool frame_skip)
|
||||
{ @autoreleasepool {
|
||||
GSDeviceMTL* dev = static_cast<GSDeviceMTL*>(g_gs_device.get());
|
||||
if (dev && m_capture_start_frame && dev->FrameNo() == m_capture_start_frame)
|
||||
if (m_capture_start_frame && FrameNo() == m_capture_start_frame)
|
||||
s_capture_next = true;
|
||||
if (frame_skip || m_window_info.type == WindowInfo::Type::Surfaceless || !g_gs_device)
|
||||
{
|
||||
ImGui::EndFrame();
|
||||
return PresentResult::FrameSkipped;
|
||||
}
|
||||
id<MTLCommandBuffer> buf = dev->GetRenderCmdBuf();
|
||||
id<MTLCommandBuffer> buf = GetRenderCmdBuf();
|
||||
m_current_drawable = MRCRetain([m_layer nextDrawable]);
|
||||
dev->EndRenderPass();
|
||||
EndRenderPass();
|
||||
if (!m_current_drawable)
|
||||
{
|
||||
[buf pushDebugGroup:@"Present Skipped"];
|
||||
[buf popDebugGroup];
|
||||
dev->FlushEncoders();
|
||||
FlushEncoders();
|
||||
ImGui::EndFrame();
|
||||
return PresentResult::FrameSkipped;
|
||||
}
|
||||
[m_pass_desc colorAttachments][0].texture = [m_current_drawable texture];
|
||||
id<MTLRenderCommandEncoder> enc = [buf renderCommandEncoderWithDescriptor:m_pass_desc];
|
||||
[enc setLabel:@"Present"];
|
||||
dev->m_current_render.encoder = MRCRetain(enc);
|
||||
m_current_render.encoder = MRCRetain(enc);
|
||||
return PresentResult::OK;
|
||||
}}
|
||||
|
||||
void GSDeviceMTL::EndPresent()
|
||||
{ @autoreleasepool {
|
||||
GSDeviceMTL* dev = static_cast<GSDeviceMTL*>(g_gs_device.get());
|
||||
pxAssertDev(dev && dev->m_current_render.encoder && dev->m_current_render_cmdbuf, "BeginPresent cmdbuf was destroyed");
|
||||
pxAssertDev(m_current_render.encoder && m_current_render_cmdbuf, "BeginPresent cmdbuf was destroyed");
|
||||
ImGui::Render();
|
||||
dev->RenderImGui(ImGui::GetDrawData());
|
||||
dev->EndRenderPass();
|
||||
RenderImGui(ImGui::GetDrawData());
|
||||
EndRenderPass();
|
||||
if (m_current_drawable)
|
||||
{
|
||||
const bool use_present_drawable = m_use_present_drawable == UsePresentDrawable::Always ||
|
||||
(m_use_present_drawable == UsePresentDrawable::IfVsync && m_vsync_mode != VsyncMode::Off);
|
||||
|
||||
if (use_present_drawable)
|
||||
[dev->m_current_render_cmdbuf presentDrawable:m_current_drawable];
|
||||
[m_current_render_cmdbuf presentDrawable:m_current_drawable];
|
||||
else
|
||||
[dev->m_current_render_cmdbuf addScheduledHandler:[drawable = std::move(m_current_drawable)](id<MTLCommandBuffer>){
|
||||
[m_current_render_cmdbuf addScheduledHandler:[drawable = std::move(m_current_drawable)](id<MTLCommandBuffer>){
|
||||
[drawable present];
|
||||
}];
|
||||
}
|
||||
dev->FlushEncoders();
|
||||
dev->FrameCompleted();
|
||||
FlushEncoders();
|
||||
FrameCompleted();
|
||||
m_current_drawable = nullptr;
|
||||
if (m_capture_start_frame)
|
||||
{
|
||||
@@ -2178,7 +2177,7 @@ void GSDeviceMTL::SendHWDraw(GSHWDrawConfig& config, id<MTLRenderCommandEncoder>
|
||||
textureBarrier(enc);
|
||||
[enc drawIndexedPrimitives:topology
|
||||
indexCount:count
|
||||
indexType:MTLIndexTypeUInt32
|
||||
indexType:MTLIndexTypeUInt16
|
||||
indexBuffer:buffer
|
||||
indexBufferOffset:off + p * sizeof(*config.indices)];
|
||||
p += count;
|
||||
@@ -2200,7 +2199,7 @@ void GSDeviceMTL::SendHWDraw(GSHWDrawConfig& config, id<MTLRenderCommandEncoder>
|
||||
textureBarrier(enc);
|
||||
[enc drawIndexedPrimitives:topology
|
||||
indexCount:config.indices_per_prim
|
||||
indexType:MTLIndexTypeUInt32
|
||||
indexType:MTLIndexTypeUInt16
|
||||
indexBuffer:buffer
|
||||
indexBufferOffset:off + p * sizeof(*config.indices)];
|
||||
}
|
||||
@@ -2217,7 +2216,7 @@ void GSDeviceMTL::SendHWDraw(GSHWDrawConfig& config, id<MTLRenderCommandEncoder>
|
||||
|
||||
[enc drawIndexedPrimitives:topology
|
||||
indexCount:config.nindices
|
||||
indexType:MTLIndexTypeUInt32
|
||||
indexType:MTLIndexTypeUInt16
|
||||
indexBuffer:buffer
|
||||
indexBufferOffset:off];
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ bool GSDeviceOGL::Create(const WindowInfo& wi, VsyncMode vsync)
|
||||
GLint max_vertex_ssbos = 0;
|
||||
glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &max_vertex_ssbos);
|
||||
DevCon.WriteLn("GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS: %d", max_vertex_ssbos);
|
||||
m_features.vs_expand = (max_vertex_ssbos > 0);
|
||||
m_features.vs_expand = (max_vertex_ssbos > 0 && GLAD_GL_ARB_gpu_shader5);
|
||||
}
|
||||
if (!m_features.vs_expand)
|
||||
Console.Warning("Vertex expansion is not supported. This will reduce performance.");
|
||||
@@ -876,8 +876,8 @@ void GSDeviceOGL::DrawPrimitive()
|
||||
void GSDeviceOGL::DrawIndexedPrimitive()
|
||||
{
|
||||
g_perfmon.Put(GSPerfMon::DrawCalls, 1);
|
||||
glDrawElementsBaseVertex(m_draw_topology, static_cast<u32>(m_index.count), GL_UNSIGNED_INT,
|
||||
reinterpret_cast<void*>(static_cast<u32>(m_index.start) * sizeof(u32)), static_cast<GLint>(m_vertex.start));
|
||||
glDrawElementsBaseVertex(m_draw_topology, static_cast<u32>(m_index.count), GL_UNSIGNED_SHORT,
|
||||
reinterpret_cast<void*>(static_cast<u32>(m_index.start) * sizeof(u16)), static_cast<GLint>(m_vertex.start));
|
||||
}
|
||||
|
||||
void GSDeviceOGL::DrawIndexedPrimitive(int offset, int count)
|
||||
@@ -885,8 +885,8 @@ void GSDeviceOGL::DrawIndexedPrimitive(int offset, int count)
|
||||
//ASSERT(offset + count <= (int)m_index.count);
|
||||
|
||||
g_perfmon.Put(GSPerfMon::DrawCalls, 1);
|
||||
glDrawElementsBaseVertex(m_draw_topology, count, GL_UNSIGNED_INT,
|
||||
reinterpret_cast<void*>((static_cast<u32>(m_index.start) + static_cast<u32>(offset)) * sizeof(u32)),
|
||||
glDrawElementsBaseVertex(m_draw_topology, count, GL_UNSIGNED_SHORT,
|
||||
reinterpret_cast<void*>((static_cast<u32>(m_index.start) + static_cast<u32>(offset)) * sizeof(u16)),
|
||||
static_cast<GLint>(m_vertex.start));
|
||||
}
|
||||
|
||||
@@ -1134,7 +1134,9 @@ std::string GSDeviceOGL::GenGlslHeader(const std::string_view& entry, GLenum typ
|
||||
else
|
||||
{
|
||||
header = "#version 330 core\n";
|
||||
header += "#extension GL_ARB_shading_language_420pack: require\n";
|
||||
header += "#extension GL_ARB_shading_language_420pack : require\n";
|
||||
if (GLAD_GL_ARB_gpu_shader5)
|
||||
header += "#extension GL_ARB_gpu_shader5 : require\n";
|
||||
if (m_features.vs_expand)
|
||||
header += "#extension GL_ARB_shader_storage_buffer_object: require\n";
|
||||
}
|
||||
@@ -1548,15 +1550,15 @@ void GSDeviceOGL::DrawMultiStretchRects(
|
||||
void GSDeviceOGL::DoMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, const GSVector2& ds)
|
||||
{
|
||||
const u32 vertex_reserve_size = num_rects * 4 * sizeof(GSVertexPT1);
|
||||
const u32 index_reserve_size = num_rects * 6 * sizeof(u32);
|
||||
const u32 index_reserve_size = num_rects * 6 * sizeof(u16);
|
||||
auto vertex_map = m_vertex_stream_buffer->Map(sizeof(GSVertexPT1), vertex_reserve_size);
|
||||
auto index_map = m_index_stream_buffer->Map(sizeof(u32), index_reserve_size);
|
||||
auto index_map = m_index_stream_buffer->Map(sizeof(u16), index_reserve_size);
|
||||
m_vertex.start = vertex_map.index_aligned;
|
||||
m_index.start = index_map.index_aligned;
|
||||
|
||||
// Don't use primitive restart here, it ends up slower on some drivers.
|
||||
GSVertexPT1* verts = reinterpret_cast<GSVertexPT1*>(vertex_map.pointer);
|
||||
u32* idx = reinterpret_cast<u32*>(index_map.pointer);
|
||||
u16* idx = reinterpret_cast<u16*>(index_map.pointer);
|
||||
u32 icount = 0;
|
||||
u32 vcount = 0;
|
||||
for (u32 i = 0; i < num_rects; i++)
|
||||
@@ -1587,7 +1589,7 @@ void GSDeviceOGL::DoMultiStretchRects(const MultiStretchRect* rects, u32 num_rec
|
||||
m_vertex.count = vcount;
|
||||
m_index.count = icount;
|
||||
m_vertex_stream_buffer->Unmap(vcount * sizeof(GSVertexPT1));
|
||||
m_index_stream_buffer->Unmap(icount * sizeof(u32));
|
||||
m_index_stream_buffer->Unmap(icount * sizeof(u16));
|
||||
|
||||
PSSetShaderResource(0, rects[0].src);
|
||||
PSSetSamplerState(rects[0].linear ? m_convert.ln : m_convert.pt);
|
||||
@@ -1807,8 +1809,8 @@ void GSDeviceOGL::IASetVertexBuffer(const void* vertices, size_t count)
|
||||
|
||||
void GSDeviceOGL::IASetIndexBuffer(const void* index, size_t count)
|
||||
{
|
||||
const u32 size = static_cast<u32>(count) * sizeof(u32);
|
||||
auto res = m_index_stream_buffer->Map(sizeof(u32), size);
|
||||
const u32 size = static_cast<u32>(count) * sizeof(u16);
|
||||
auto res = m_index_stream_buffer->Map(sizeof(u16), size);
|
||||
m_index.start = res.index_aligned;
|
||||
m_index.count = count;
|
||||
std::memcpy(res.pointer, index, size);
|
||||
@@ -1999,18 +2001,7 @@ void GSDeviceOGL::RenderImGui()
|
||||
m_vertex_stream_buffer->Unmap(size);
|
||||
}
|
||||
|
||||
// Bit awkward, because this is using 16-bit indices, not 32-bit.
|
||||
u32 index_start;
|
||||
{
|
||||
static_assert(sizeof(ImDrawIdx) == sizeof(u16));
|
||||
|
||||
const u32 size = static_cast<u32>(cmd_list->IdxBuffer.Size) * sizeof(ImDrawIdx);
|
||||
auto res = m_index_stream_buffer->Map(sizeof(u16), size);
|
||||
index_start = res.index_aligned;
|
||||
std::memcpy(res.pointer, cmd_list->IdxBuffer.Data, size);
|
||||
m_index_stream_buffer->Unmap(size);
|
||||
m_index_stream_buffer->Bind();
|
||||
}
|
||||
IASetIndexBuffer(cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size);
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
@@ -2038,7 +2029,7 @@ void GSDeviceOGL::RenderImGui()
|
||||
}
|
||||
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT,
|
||||
(void*)(intptr_t)((pcmd->IdxOffset + index_start) * sizeof(ImDrawIdx)), pcmd->VtxOffset + vertex_start);
|
||||
(void*)(intptr_t)((pcmd->IdxOffset + m_index.start) * sizeof(ImDrawIdx)), pcmd->VtxOffset + vertex_start);
|
||||
}
|
||||
|
||||
g_perfmon.Put(GSPerfMon::DrawCalls, cmd_list->CmdBuffer.Size);
|
||||
@@ -2165,6 +2156,8 @@ void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVecto
|
||||
GSTextureOGL* RT = static_cast<GSTextureOGL*>(rt);
|
||||
GSTextureOGL* DS = static_cast<GSTextureOGL*>(ds);
|
||||
|
||||
g_perfmon.Put(GSPerfMon::RenderPasses, static_cast<double>(GLState::rt != RT || GLState::ds != DS));
|
||||
|
||||
OMSetFBO(m_fbo);
|
||||
if (rt)
|
||||
{
|
||||
@@ -2431,13 +2424,17 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
OMSetBlendState(config.blend.enable, s_gl_blend_factors[config.blend.src_factor],
|
||||
s_gl_blend_factors[config.blend.dst_factor], s_gl_blend_ops[config.blend.op],
|
||||
config.blend.constant_enable, config.blend.constant);
|
||||
OMSetColorMaskState(config.colormask);
|
||||
|
||||
// avoid changing framebuffer just to switch from rt+depth to rt and vice versa
|
||||
GSTexture* draw_rt = hdr_rt ? hdr_rt : config.rt;
|
||||
GSTexture* draw_ds = config.ds;
|
||||
if (!draw_ds && GLState::ds && GLState::rt == draw_rt && config.tex != GLState::ds &&
|
||||
GLState::ds->GetSize() == draw_rt->GetSize())
|
||||
OMColorMaskSelector draw_colormask = config.colormask;
|
||||
if (!draw_rt && GLState::rt && GLState::ds == draw_ds && GLState::rt->GetSize() == draw_ds->GetSize())
|
||||
{
|
||||
draw_rt = GLState::rt;
|
||||
draw_colormask.wrgba = 0;
|
||||
}
|
||||
else if (!draw_ds && GLState::ds && GLState::rt == draw_rt && GLState::ds->GetSize() == draw_rt->GetSize())
|
||||
{
|
||||
// should already be always-pass.
|
||||
draw_ds = GLState::ds;
|
||||
@@ -2446,6 +2443,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
|
||||
OMSetRenderTargets(draw_rt, draw_ds, &config.scissor);
|
||||
OMSetColorMaskState(draw_colormask);
|
||||
SetupOM(config.depth);
|
||||
|
||||
SendHWDraw(config, psel.ps.IsFeedbackLoop());
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "GS/Renderers/OpenGL/GSDeviceOGL.h"
|
||||
#include "GS/Renderers/OpenGL/GSTextureOGL.h"
|
||||
#include "GS/Renderers/OpenGL/GLState.h"
|
||||
#include "GS/GSExtra.h"
|
||||
#include "GS/GSPerfMon.h"
|
||||
#include "GS/GSPng.h"
|
||||
#include "GS/GSGL.h"
|
||||
@@ -476,7 +477,7 @@ std::unique_ptr<GSDownloadTextureOGL> GSDownloadTextureOGL::Create(u32 width, u3
|
||||
}
|
||||
|
||||
// Fallback to glReadPixels() + CPU buffer.
|
||||
u8* cpu_buffer = static_cast<u8*>(_aligned_malloc(buffer_size, 32));
|
||||
u8* cpu_buffer = static_cast<u8*>(_aligned_malloc(buffer_size, VECTOR_ALIGNMENT));
|
||||
if (!cpu_buffer)
|
||||
return {};
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ typedef GSVector4 VectorF;
|
||||
#define LOCAL_STEP local.d4
|
||||
#endif
|
||||
|
||||
void GSDrawScanline::CSetupPrim(const GSVertexSW* vertex, const u32* index, const GSVertexSW& dscan, GSScanlineLocalData& local)
|
||||
void GSDrawScanline::CSetupPrim(const GSVertexSW* vertex, const u16* index, const GSVertexSW& dscan, GSScanlineLocalData& local)
|
||||
{
|
||||
const GSScanlineGlobalData& global = GlobalFromLocal(local);
|
||||
GSScanlineSelector sel = global.sel;
|
||||
@@ -451,10 +451,14 @@ __ri static void WritePixel(const T& src, int addr, int i, u32 psm, const GSScan
|
||||
}
|
||||
|
||||
void GSDrawScanline::CDrawScanline(int pixels, int left, int top, const GSVertexSW& scan, GSScanlineLocalData& local)
|
||||
{
|
||||
CDrawScanline(pixels, left, top, scan, local, GlobalFromLocal(local).sel);
|
||||
}
|
||||
|
||||
__ri void GSDrawScanline::CDrawScanline(int pixels, int left, int top, const GSVertexSW& scan, GSScanlineLocalData& local, GSScanlineSelector sel)
|
||||
{
|
||||
const GSScanlineGlobalData& global = GlobalFromLocal(local);
|
||||
|
||||
GSScanlineSelector sel = global.sel;
|
||||
constexpr int vlen = sizeof(VectorF) / sizeof(float);
|
||||
|
||||
#if _M_SSE < 0x501
|
||||
@@ -1729,17 +1733,10 @@ void GSDrawScanline::CDrawScanline(int pixels, int left, int top, const GSVertex
|
||||
|
||||
void GSDrawScanline::CDrawEdge(int pixels, int left, int top, const GSVertexSW& scan, GSScanlineLocalData& local)
|
||||
{
|
||||
// This sucks. But so does not jitting!
|
||||
const GSScanlineGlobalData* old_gd = local.gd;
|
||||
GSScanlineGlobalData gd;
|
||||
std::memcpy(&gd, &local.gd, sizeof(gd));
|
||||
gd.sel.zwrite = 0;
|
||||
gd.sel.edge = 1;
|
||||
local.gd = &gd;
|
||||
|
||||
CDrawScanline(pixels, left, top, scan, local);
|
||||
|
||||
local.gd = old_gd;
|
||||
GSScanlineSelector sel = local.gd->sel;
|
||||
sel.zwrite = 0;
|
||||
sel.edge = 1;
|
||||
CDrawScanline(pixels, left, top, scan, local, sel);
|
||||
}
|
||||
|
||||
template <class T, bool masked>
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
~GSDrawScanline() override;
|
||||
|
||||
/// Function pointer types which we call back into.
|
||||
using SetupPrimPtr = void(*)(const GSVertexSW* vertex, const u32* index, const GSVertexSW& dscan, GSScanlineLocalData& local);
|
||||
using SetupPrimPtr = void(*)(const GSVertexSW* vertex, const u16* index, const GSVertexSW& dscan, GSScanlineLocalData& local);
|
||||
using DrawScanlinePtr = void(*)(int pixels, int left, int top, const GSVertexSW& scan, GSScanlineLocalData& local);
|
||||
|
||||
/// Flushes the code cache, forcing everything to be recompiled.
|
||||
@@ -60,9 +60,10 @@ private:
|
||||
GSCodeGeneratorFunctionMap<GSSetupPrimCodeGenerator, u64, SetupPrimPtr> m_sp_map;
|
||||
GSCodeGeneratorFunctionMap<GSDrawScanlineCodeGenerator, u64, DrawScanlinePtr> m_ds_map;
|
||||
|
||||
static void CSetupPrim(const GSVertexSW* vertex, const u32* index, const GSVertexSW& dscan, GSScanlineLocalData& local);
|
||||
static void CSetupPrim(const GSVertexSW* vertex, const u16* index, const GSVertexSW& dscan, GSScanlineLocalData& local);
|
||||
static void CDrawScanline(int pixels, int left, int top, const GSVertexSW& scan, GSScanlineLocalData& local);
|
||||
static void CDrawEdge(int pixels, int left, int top, const GSVertexSW& scan, GSScanlineLocalData& local);
|
||||
__ri static void CDrawScanline(int pixels, int left, int top, const GSVertexSW& scan, GSScanlineLocalData& local, GSScanlineSelector sel);
|
||||
};
|
||||
|
||||
MULTI_ISA_UNSHARED_END
|
||||
|
||||
@@ -91,7 +91,8 @@ GSDrawScanlineCodeGenerator::GSDrawScanlineCodeGenerator(u64 key, void* code, si
|
||||
|
||||
if (shouldUseCDrawScanline(key))
|
||||
{
|
||||
jmp(reinterpret_cast<const void*>(&GSDrawScanline::CDrawScanline));
|
||||
jmp(reinterpret_cast<const void*>(static_cast<void (*)(int, int, int, const GSVertexSW&, GSScanlineLocalData&)>(
|
||||
&GSDrawScanline::CDrawScanline)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ GSRasterizer::GSRasterizer(GSDrawScanline* ds, int id, int threads)
|
||||
|
||||
m_thread_height = compute_best_thread_height(threads);
|
||||
|
||||
m_edge.buff = static_cast<GSVertexSW*>(_aligned_malloc(sizeof(GSVertexSW) * 2048, 32));
|
||||
m_edge.buff = static_cast<GSVertexSW*>(_aligned_malloc(sizeof(GSVertexSW) * 2048, VECTOR_ALIGNMENT));
|
||||
m_edge.count = 0;
|
||||
if (!m_edge.buff)
|
||||
throw std::bad_alloc();
|
||||
@@ -154,10 +154,10 @@ void GSRasterizer::Draw(GSRasterizerData& data)
|
||||
const GSVertexSW* vertex = data.vertex;
|
||||
const GSVertexSW* vertex_end = data.vertex + data.vertex_count;
|
||||
|
||||
const u32* index = data.index;
|
||||
const u32* index_end = data.index + data.index_count;
|
||||
const u16* index = data.index;
|
||||
const u16* index_end = data.index + data.index_count;
|
||||
|
||||
u32 tmp_index[] = {0, 1, 2};
|
||||
static constexpr u16 tmp_index[] = {0, 1, 2};
|
||||
|
||||
bool scissor_test = !data.bbox.eq(data.bbox.rintersect(data.scissor));
|
||||
|
||||
@@ -261,7 +261,7 @@ void GSRasterizer::Draw(GSRasterizerData& data)
|
||||
}
|
||||
|
||||
template <bool scissor_test>
|
||||
void GSRasterizer::DrawPoint(const GSVertexSW* vertex, int vertex_count, const u32* index, int index_count)
|
||||
void GSRasterizer::DrawPoint(const GSVertexSW* vertex, int vertex_count, const u16* index, int index_count)
|
||||
{
|
||||
m_primcount++;
|
||||
|
||||
@@ -286,7 +286,7 @@ void GSRasterizer::DrawPoint(const GSVertexSW* vertex, int vertex_count, const u
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 tmp_index[1] = {0};
|
||||
static constexpr u16 tmp_index[1] = {0};
|
||||
|
||||
for (int i = 0; i < vertex_count; i++, vertex++)
|
||||
{
|
||||
@@ -307,7 +307,7 @@ void GSRasterizer::DrawPoint(const GSVertexSW* vertex, int vertex_count, const u
|
||||
}
|
||||
}
|
||||
|
||||
void GSRasterizer::DrawLine(const GSVertexSW* vertex, const u32* index)
|
||||
void GSRasterizer::DrawLine(const GSVertexSW* vertex, const u16* index)
|
||||
{
|
||||
m_primcount++;
|
||||
|
||||
@@ -425,7 +425,7 @@ static const u8 s_ysort[8][4] =
|
||||
|
||||
#if _M_SSE >= 0x501
|
||||
|
||||
void GSRasterizer::DrawTriangle(const GSVertexSW* vertex, const u32* index)
|
||||
void GSRasterizer::DrawTriangle(const GSVertexSW* vertex, const u16* index)
|
||||
{
|
||||
m_primcount++;
|
||||
|
||||
@@ -606,7 +606,7 @@ void GSRasterizer::DrawTriangleSection(int top, int bottom, GSVertexSW2& RESTRIC
|
||||
|
||||
#else
|
||||
|
||||
void GSRasterizer::DrawTriangle(const GSVertexSW* vertex, const u32* index)
|
||||
void GSRasterizer::DrawTriangle(const GSVertexSW* vertex, const u16* index)
|
||||
{
|
||||
m_primcount++;
|
||||
|
||||
@@ -784,7 +784,7 @@ void GSRasterizer::DrawTriangleSection(int top, int bottom, GSVertexSW& RESTRICT
|
||||
|
||||
#endif
|
||||
|
||||
void GSRasterizer::DrawSprite(const GSVertexSW* vertex, const u32* index)
|
||||
void GSRasterizer::DrawSprite(const GSVertexSW* vertex, const u16* index)
|
||||
{
|
||||
m_primcount++;
|
||||
|
||||
@@ -1082,7 +1082,7 @@ void GSRasterizer::AddScanline(GSVertexSW* e, int pixels, int left, int top, con
|
||||
AddScanlineInfo(e, pixels, left, top);
|
||||
}
|
||||
|
||||
void GSRasterizer::Flush(const GSVertexSW* vertex, const u32* index, const GSVertexSW& dscan, bool edge /* = false */)
|
||||
void GSRasterizer::Flush(const GSVertexSW* vertex, const u16* index, const GSVertexSW& dscan, bool edge /* = false */)
|
||||
{
|
||||
// TODO: on win64 this could be the place where xmm6-15 are preserved (not by each DrawScanline)
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
u8* buff;
|
||||
GSVertexSW* vertex;
|
||||
int vertex_count;
|
||||
u32* index;
|
||||
u16* index;
|
||||
int index_count;
|
||||
u64 frame;
|
||||
u64 start;
|
||||
@@ -101,10 +101,10 @@ protected:
|
||||
__forceinline bool HasEdge() const { return (m_draw_edge != nullptr); }
|
||||
|
||||
template <bool scissor_test>
|
||||
void DrawPoint(const GSVertexSW* vertex, int vertex_count, const u32* index, int index_count);
|
||||
void DrawLine(const GSVertexSW* vertex, const u32* index);
|
||||
void DrawTriangle(const GSVertexSW* vertex, const u32* index);
|
||||
void DrawSprite(const GSVertexSW* vertex, const u32* index);
|
||||
void DrawPoint(const GSVertexSW* vertex, int vertex_count, const u16* index, int index_count);
|
||||
void DrawLine(const GSVertexSW* vertex, const u16* index);
|
||||
void DrawTriangle(const GSVertexSW* vertex, const u16* index);
|
||||
void DrawSprite(const GSVertexSW* vertex, const u16* index);
|
||||
|
||||
#if _M_SSE >= 0x501
|
||||
__forceinline void DrawTriangleSection(int top, int bottom, GSVertexSW2& RESTRICT edge, const GSVertexSW2& RESTRICT dedge, const GSVertexSW2& RESTRICT dscan, const GSVector4& RESTRICT p0);
|
||||
@@ -115,7 +115,7 @@ protected:
|
||||
void DrawEdge(const GSVertexSW& v0, const GSVertexSW& v1, const GSVertexSW& dv, int orientation, int side);
|
||||
|
||||
__forceinline void AddScanline(GSVertexSW* e, int pixels, int left, int top, const GSVertexSW& scan);
|
||||
__forceinline void Flush(const GSVertexSW* vertex, const u32* index, const GSVertexSW& dscan, bool edge = false);
|
||||
__forceinline void Flush(const GSVertexSW* vertex, const u16* index, const GSVertexSW& dscan, bool edge = false);
|
||||
|
||||
__forceinline void DrawScanline(int pixels, int left, int top, const GSVertexSW& scan);
|
||||
__forceinline void DrawEdge(int pixels, int left, int top, const GSVertexSW& scan);
|
||||
|
||||
@@ -39,7 +39,7 @@ GSRendererSW::GSRendererSW(int threads)
|
||||
m_tc = std::make_unique<GSTextureCacheSW>();
|
||||
m_rl = GSRasterizerList::Create(threads);
|
||||
|
||||
m_output = (u8*)_aligned_malloc(1024 * 1024 * sizeof(u32), 32);
|
||||
m_output = (u8*)_aligned_malloc(1024 * 1024 * sizeof(u32), VECTOR_ALIGNMENT);
|
||||
|
||||
std::fill(std::begin(m_fzb_pages), std::end(m_fzb_pages), 0);
|
||||
std::fill(std::begin(m_tex_pages), std::end(m_tex_pages), 0);
|
||||
@@ -343,7 +343,7 @@ void GSRendererSW::Draw()
|
||||
sd->buff = (u8*)m_vertex_heap.alloc(sizeof(GSVertexSW) * ((m_vertex.next + 1) & ~1) + sizeof(u32) * m_index.tail, 64);
|
||||
sd->vertex = (GSVertexSW*)sd->buff;
|
||||
sd->vertex_count = m_vertex.next;
|
||||
sd->index = (u32*)(sd->buff + sizeof(GSVertexSW) * ((m_vertex.next + 1) & ~1));
|
||||
sd->index = (u16*)(sd->buff + sizeof(GSVertexSW) * ((m_vertex.next + 1) & ~1));
|
||||
sd->index_count = m_index.tail;
|
||||
sd->scanmsk_value = m_draw_env->SCANMSK.MSK;
|
||||
|
||||
@@ -354,7 +354,7 @@ void GSRendererSW::Draw()
|
||||
|
||||
GSVertexSW::s_cvb[m_vt.m_primclass][PRIM->TME][PRIM->FST][q_div](m_context, sd->vertex, m_vertex.buff, m_vertex.next);
|
||||
|
||||
memcpy(sd->index, m_index.buff, sizeof(u32) * m_index.tail);
|
||||
std::memcpy(sd->index, m_index.buff, sizeof(u16) * m_index.tail);
|
||||
|
||||
GSVector4i scissor = GSVector4i(context->scissor.in);
|
||||
GSVector4i bbox = GSVector4i(m_vt.m_min.p.floor().xyxy(m_vt.m_max.p.ceil()));
|
||||
@@ -1046,7 +1046,7 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data)
|
||||
{
|
||||
gd.sel.tlu = 1;
|
||||
|
||||
gd.clut = (u32*)m_vertex_heap.alloc(sizeof(u32) * 256, 32); // FIXME: might address uninitialized data of the texture (0xCD) that is not in 0-15 range for 4-bpp formats
|
||||
gd.clut = (u32*)m_vertex_heap.alloc(sizeof(u32) * 256, VECTOR_ALIGNMENT); // FIXME: might address uninitialized data of the texture (0xCD) that is not in 0-15 range for 4-bpp formats
|
||||
|
||||
memcpy(gd.clut, (const u32*)m_mem.m_clut, sizeof(u32) * GSLocalMemory::m_psm[context->TEX0.PSM].pal);
|
||||
}
|
||||
@@ -1333,7 +1333,7 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data)
|
||||
ExpandDIMX(m_dimx, env.DIMX);
|
||||
}
|
||||
|
||||
gd.dimx = (GSVector4i*)m_vertex_heap.alloc(sizeof(m_dimx), 32);
|
||||
gd.dimx = (GSVector4i*)m_vertex_heap.alloc(sizeof(m_dimx), VECTOR_ALIGNMENT);
|
||||
|
||||
std::memcpy(gd.dimx, m_dimx, sizeof(m_dimx));
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ void GSSetupPrimCodeGenerator2::Depth_XMM()
|
||||
{
|
||||
// GSVector4 p = vertex[index[1]].p;
|
||||
|
||||
mov(eax, ptr[_index + sizeof(u32) * 1]);
|
||||
movzx(eax, word[_index + sizeof(u16) * 1]);
|
||||
shl(eax, 6); // * sizeof(GSVertexSW)
|
||||
add(rax, _64_vertex);
|
||||
|
||||
@@ -299,7 +299,7 @@ void GSSetupPrimCodeGenerator2::Depth_YMM()
|
||||
{
|
||||
// GSVector4 p = vertex[index[1]].p;
|
||||
|
||||
mov(eax, ptr[_index + sizeof(u32) * 1]);
|
||||
movzx(eax, word[_index + sizeof(u16) * 1]);
|
||||
shl(eax, 6); // * sizeof(GSVertexSW)
|
||||
add(rax, _64_vertex);
|
||||
|
||||
@@ -504,7 +504,7 @@ void GSSetupPrimCodeGenerator2::Color()
|
||||
|
||||
if (!(m_sel.prim == GS_SPRITE_CLASS && (m_en.z || m_en.f))) // if this is a sprite, the last vertex was already loaded in Depth()
|
||||
{
|
||||
mov(eax, ptr[_index + sizeof(u32) * last]);
|
||||
movzx(eax, word[_index + sizeof(u16) * last]);
|
||||
shl(eax, 6); // * sizeof(GSVertexSW)
|
||||
add(rax, _64_vertex);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "GSTextureCacheSW.h"
|
||||
#include "GS/Renderers/SW/GSTextureCacheSW.h"
|
||||
#include "GS/GSExtra.h"
|
||||
|
||||
GSTextureCacheSW::GSTextureCacheSW() = default;
|
||||
|
||||
@@ -233,14 +234,11 @@ bool GSTextureCacheSW::Texture::Update(const GSVector4i& rect)
|
||||
|
||||
if (m_buff == NULL)
|
||||
{
|
||||
u32 pitch = (1 << m_tw) << shift;
|
||||
const u32 pitch = (1 << m_tw) << shift;
|
||||
|
||||
m_buff = _aligned_malloc(pitch * th * 4, 32);
|
||||
|
||||
if (m_buff == NULL)
|
||||
{
|
||||
m_buff = _aligned_malloc(pitch * th * 4, VECTOR_ALIGNMENT);
|
||||
if (!m_buff)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
GSLocalMemory& mem = g_gs_renderer->m_mem;
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "GSTextureSW.h"
|
||||
#include "GS/Renderers/SW/GSTextureSW.h"
|
||||
#include "GS/GSExtra.h"
|
||||
#include "GS/GSPng.h"
|
||||
|
||||
GSTextureSW::GSTextureSW(Type type, int width, int height)
|
||||
@@ -24,7 +25,7 @@ GSTextureSW::GSTextureSW(Type type, int width, int height)
|
||||
m_type = type;
|
||||
m_format = Format::Invalid;
|
||||
m_pitch = ((width << 2) + 31) & ~31;
|
||||
m_data = _aligned_malloc(m_pitch * height, 32);
|
||||
m_data = _aligned_malloc(m_pitch * height, VECTOR_ALIGNMENT);
|
||||
}
|
||||
|
||||
GSTextureSW::~GSTextureSW()
|
||||
|
||||
@@ -475,6 +475,7 @@ void GSDeviceVK::EndPresent()
|
||||
VkCommandBuffer cmdbuffer = g_vulkan_context->GetCurrentCommandBuffer();
|
||||
vkCmdEndRenderPass(g_vulkan_context->GetCurrentCommandBuffer());
|
||||
m_swap_chain->GetCurrentTexture().TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
g_perfmon.Put(GSPerfMon::RenderPasses, 1);
|
||||
|
||||
g_vulkan_context->SubmitCommandBuffer(m_swap_chain.get(), !m_swap_chain->IsPresentModeSynchronizing());
|
||||
g_vulkan_context->MoveToNextCommandBuffer();
|
||||
@@ -578,7 +579,7 @@ bool GSDeviceVK::CheckFeatures()
|
||||
const bool isAMD = (vendorID == 0x1002 || vendorID == 0x1022);
|
||||
// const bool isNVIDIA = (vendorID == 0x10DE);
|
||||
|
||||
m_features.framebuffer_fetch = g_vulkan_context->GetOptionalExtensions().vk_arm_rasterization_order_attachment_access && !GSConfig.DisableFramebufferFetch;
|
||||
m_features.framebuffer_fetch = g_vulkan_context->GetOptionalExtensions().vk_ext_rasterization_order_attachment_access && !GSConfig.DisableFramebufferFetch;
|
||||
m_features.texture_barrier = GSConfig.OverrideTextureBarriers != 0;
|
||||
m_features.broken_point_sampler = isAMD;
|
||||
// Usually, geometry shader indicates primid support
|
||||
@@ -955,13 +956,13 @@ void GSDeviceVK::DoMultiStretchRects(
|
||||
{
|
||||
// Set up vertices first.
|
||||
const u32 vertex_reserve_size = num_rects * 4 * sizeof(GSVertexPT1);
|
||||
const u32 index_reserve_size = num_rects * 6 * sizeof(u32);
|
||||
const u32 index_reserve_size = num_rects * 6 * sizeof(u16);
|
||||
if (!m_vertex_stream_buffer.ReserveMemory(vertex_reserve_size, sizeof(GSVertexPT1)) ||
|
||||
!m_index_stream_buffer.ReserveMemory(index_reserve_size, sizeof(u32)))
|
||||
!m_index_stream_buffer.ReserveMemory(index_reserve_size, sizeof(u16)))
|
||||
{
|
||||
ExecuteCommandBufferAndRestartRenderPass(false, "Uploading bytes to vertex buffer");
|
||||
if (!m_vertex_stream_buffer.ReserveMemory(vertex_reserve_size, sizeof(GSVertexPT1)) ||
|
||||
!m_index_stream_buffer.ReserveMemory(index_reserve_size, sizeof(u32)))
|
||||
!m_index_stream_buffer.ReserveMemory(index_reserve_size, sizeof(u16)))
|
||||
{
|
||||
pxFailRel("Failed to reserve space for vertices");
|
||||
}
|
||||
@@ -971,7 +972,7 @@ void GSDeviceVK::DoMultiStretchRects(
|
||||
// Don't use primitive restart here, it ends up slower on some drivers.
|
||||
const GSVector2 ds(static_cast<float>(dTex->GetWidth()), static_cast<float>(dTex->GetHeight()));
|
||||
GSVertexPT1* verts = reinterpret_cast<GSVertexPT1*>(m_vertex_stream_buffer.GetCurrentHostPointer());
|
||||
u32* idx = reinterpret_cast<u32*>(m_index_stream_buffer.GetCurrentHostPointer());
|
||||
u16* idx = reinterpret_cast<u16*>(m_index_stream_buffer.GetCurrentHostPointer());
|
||||
u32 icount = 0;
|
||||
u32 vcount = 0;
|
||||
for (u32 i = 0; i < num_rects; i++)
|
||||
@@ -1001,11 +1002,11 @@ void GSDeviceVK::DoMultiStretchRects(
|
||||
|
||||
m_vertex.start = m_vertex_stream_buffer.GetCurrentOffset() / sizeof(GSVertexPT1);
|
||||
m_vertex.count = vcount;
|
||||
m_index.start = m_index_stream_buffer.GetCurrentOffset() / sizeof(u32);
|
||||
m_index.start = m_index_stream_buffer.GetCurrentOffset() / sizeof(u16);
|
||||
m_index.count = icount;
|
||||
m_vertex_stream_buffer.CommitMemory(vcount * sizeof(GSVertexPT1));
|
||||
m_index_stream_buffer.CommitMemory(icount * sizeof(u32));
|
||||
SetIndexBuffer(m_index_stream_buffer.GetBuffer(), 0, VK_INDEX_TYPE_UINT32);
|
||||
m_index_stream_buffer.CommitMemory(icount * sizeof(u16));
|
||||
SetIndexBuffer(m_index_stream_buffer.GetBuffer(), 0, VK_INDEX_TYPE_UINT16);
|
||||
|
||||
// Even though we're batching, a cmdbuffer submit could've messed this up.
|
||||
const GSVector4i rc(dTex->GetRect());
|
||||
@@ -1368,21 +1369,21 @@ void GSDeviceVK::IASetVertexBuffer(const void* vertex, size_t stride, size_t cou
|
||||
|
||||
void GSDeviceVK::IASetIndexBuffer(const void* index, size_t count)
|
||||
{
|
||||
const u32 size = sizeof(u32) * static_cast<u32>(count);
|
||||
if (!m_index_stream_buffer.ReserveMemory(size, sizeof(u32)))
|
||||
const u32 size = sizeof(u16) * static_cast<u32>(count);
|
||||
if (!m_index_stream_buffer.ReserveMemory(size, sizeof(u16)))
|
||||
{
|
||||
ExecuteCommandBufferAndRestartRenderPass(false, "Uploading bytes to index buffer");
|
||||
if (!m_index_stream_buffer.ReserveMemory(size, sizeof(u32)))
|
||||
if (!m_index_stream_buffer.ReserveMemory(size, sizeof(u16)))
|
||||
pxFailRel("Failed to reserve space for vertices");
|
||||
}
|
||||
|
||||
m_index.start = m_index_stream_buffer.GetCurrentOffset() / sizeof(u32);
|
||||
m_index.start = m_index_stream_buffer.GetCurrentOffset() / sizeof(u16);
|
||||
m_index.count = count;
|
||||
|
||||
std::memcpy(m_index_stream_buffer.GetCurrentHostPointer(), index, size);
|
||||
m_index_stream_buffer.CommitMemory(size);
|
||||
|
||||
SetIndexBuffer(m_index_stream_buffer.GetBuffer(), 0, VK_INDEX_TYPE_UINT32);
|
||||
SetIndexBuffer(m_index_stream_buffer.GetBuffer(), 0, VK_INDEX_TYPE_UINT16);
|
||||
}
|
||||
|
||||
void GSDeviceVK::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i& scissor, FeedbackLoopFlag feedback_loop)
|
||||
@@ -1529,6 +1530,15 @@ static void AddUtilityVertexAttributes(Vulkan::GraphicsPipelineBuilder& gpb)
|
||||
gpb.SetPrimitiveTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
|
||||
}
|
||||
|
||||
static void SetPipelineProvokingVertex(const GSDevice::FeatureSupport& features, Vulkan::GraphicsPipelineBuilder& gpb)
|
||||
{
|
||||
// We enable provoking vertex here anyway, in case it doesn't support multiple modes in the same pass.
|
||||
// Normally we wouldn't enable it on the present/swap chain, but apparently the rule is it applies to the last
|
||||
// pipeline bound before the render pass begun, and in this case, we can't bind null.
|
||||
if (features.provoking_vertex_last)
|
||||
gpb.SetProvokingVertex(VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT);
|
||||
}
|
||||
|
||||
VkShaderModule GSDeviceVK::GetUtilityVertexShader(const std::string& source, const char* replace_main = nullptr)
|
||||
{
|
||||
std::stringstream ss;
|
||||
@@ -1769,6 +1779,7 @@ bool GSDeviceVK::CompileConvertPipelines()
|
||||
ScopedGuard vs_guard([&vs]() { Vulkan::Util::SafeDestroyShaderModule(vs); });
|
||||
|
||||
Vulkan::GraphicsPipelineBuilder gpb;
|
||||
SetPipelineProvokingVertex(m_features, gpb);
|
||||
AddUtilityVertexAttributes(gpb);
|
||||
gpb.SetPipelineLayout(m_utility_pipeline_layout);
|
||||
gpb.SetDynamicViewportAndScissorState();
|
||||
@@ -1777,10 +1788,6 @@ bool GSDeviceVK::CompileConvertPipelines()
|
||||
gpb.SetNoBlendingState();
|
||||
gpb.SetVertexShader(vs);
|
||||
|
||||
// we enable provoking vertex here anyway, in case it doesn't support multiple modes in the same pass
|
||||
if (m_features.provoking_vertex_last)
|
||||
gpb.SetProvokingVertex(VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT);
|
||||
|
||||
for (ShaderConvert i = ShaderConvert::COPY; static_cast<int>(i) < static_cast<int>(ShaderConvert::Count);
|
||||
i = static_cast<ShaderConvert>(static_cast<int>(i) + 1))
|
||||
{
|
||||
@@ -1964,6 +1971,7 @@ bool GSDeviceVK::CompilePresentPipelines()
|
||||
ScopedGuard vs_guard([&vs]() { Vulkan::Util::SafeDestroyShaderModule(vs); });
|
||||
|
||||
Vulkan::GraphicsPipelineBuilder gpb;
|
||||
SetPipelineProvokingVertex(m_features, gpb);
|
||||
AddUtilityVertexAttributes(gpb);
|
||||
gpb.SetPipelineLayout(m_utility_pipeline_layout);
|
||||
gpb.SetDynamicViewportAndScissorState();
|
||||
@@ -1975,10 +1983,6 @@ bool GSDeviceVK::CompilePresentPipelines()
|
||||
gpb.SetNoStencilState();
|
||||
gpb.SetRenderPass(m_swap_chain_render_pass, 0);
|
||||
|
||||
// we enable provoking vertex here anyway, in case it doesn't support multiple modes in the same pass
|
||||
if (m_features.provoking_vertex_last)
|
||||
gpb.SetProvokingVertex(VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT);
|
||||
|
||||
for (PresentShader i = PresentShader::COPY; static_cast<int>(i) < static_cast<int>(PresentShader::Count);
|
||||
i = static_cast<PresentShader>(static_cast<int>(i) + 1))
|
||||
{
|
||||
@@ -2023,6 +2027,7 @@ bool GSDeviceVK::CompileInterlacePipelines()
|
||||
ScopedGuard vs_guard([&vs]() { Vulkan::Util::SafeDestroyShaderModule(vs); });
|
||||
|
||||
Vulkan::GraphicsPipelineBuilder gpb;
|
||||
SetPipelineProvokingVertex(m_features, gpb);
|
||||
AddUtilityVertexAttributes(gpb);
|
||||
gpb.SetPipelineLayout(m_utility_pipeline_layout);
|
||||
gpb.SetDynamicViewportAndScissorState();
|
||||
@@ -2033,10 +2038,6 @@ bool GSDeviceVK::CompileInterlacePipelines()
|
||||
gpb.SetRenderPass(rp, 0);
|
||||
gpb.SetVertexShader(vs);
|
||||
|
||||
// we enable provoking vertex here anyway, in case it doesn't support multiple modes in the same pass
|
||||
if (m_features.provoking_vertex_last)
|
||||
gpb.SetProvokingVertex(VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT);
|
||||
|
||||
for (int i = 0; i < static_cast<int>(m_interlace.size()); i++)
|
||||
{
|
||||
VkShaderModule ps = GetUtilityFragmentShader(*shader, StringUtil::StdStringFromFormat("ps_main%d", i).c_str());
|
||||
@@ -2077,6 +2078,7 @@ bool GSDeviceVK::CompileMergePipelines()
|
||||
ScopedGuard vs_guard([&vs]() { Vulkan::Util::SafeDestroyShaderModule(vs); });
|
||||
|
||||
Vulkan::GraphicsPipelineBuilder gpb;
|
||||
SetPipelineProvokingVertex(m_features, gpb);
|
||||
AddUtilityVertexAttributes(gpb);
|
||||
gpb.SetPipelineLayout(m_utility_pipeline_layout);
|
||||
gpb.SetDynamicViewportAndScissorState();
|
||||
@@ -2086,10 +2088,6 @@ bool GSDeviceVK::CompileMergePipelines()
|
||||
gpb.SetRenderPass(rp, 0);
|
||||
gpb.SetVertexShader(vs);
|
||||
|
||||
// we enable provoking vertex here anyway, in case it doesn't support multiple modes in the same pass
|
||||
if (m_features.provoking_vertex_last)
|
||||
gpb.SetProvokingVertex(VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT);
|
||||
|
||||
for (int i = 0; i < static_cast<int>(m_merge.size()); i++)
|
||||
{
|
||||
VkShaderModule ps = GetUtilityFragmentShader(*shader, StringUtil::StdStringFromFormat("ps_main%d", i).c_str());
|
||||
@@ -2119,6 +2117,7 @@ bool GSDeviceVK::CompilePostProcessingPipelines()
|
||||
return false;
|
||||
|
||||
Vulkan::GraphicsPipelineBuilder gpb;
|
||||
SetPipelineProvokingVertex(m_features, gpb);
|
||||
AddUtilityVertexAttributes(gpb);
|
||||
gpb.SetPipelineLayout(m_utility_pipeline_layout);
|
||||
gpb.SetDynamicViewportAndScissorState();
|
||||
@@ -2128,10 +2127,6 @@ bool GSDeviceVK::CompilePostProcessingPipelines()
|
||||
gpb.SetNoBlendingState();
|
||||
gpb.SetRenderPass(rp, 0);
|
||||
|
||||
// we enable provoking vertex here anyway, in case it doesn't support multiple modes in the same pass
|
||||
if (m_features.provoking_vertex_last)
|
||||
gpb.SetProvokingVertex(VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT);
|
||||
|
||||
{
|
||||
std::optional<std::string> vshader = Host::ReadResourceFileToString("shaders/vulkan/convert.glsl");
|
||||
if (!vshader)
|
||||
@@ -2267,6 +2262,7 @@ bool GSDeviceVK::CompileImGuiPipeline()
|
||||
ScopedGuard ps_guard([&ps]() { Vulkan::Util::SafeDestroyShaderModule(ps); });
|
||||
|
||||
Vulkan::GraphicsPipelineBuilder gpb;
|
||||
SetPipelineProvokingVertex(m_features, gpb);
|
||||
gpb.SetPipelineLayout(m_utility_pipeline_layout);
|
||||
gpb.SetRenderPass(m_swap_chain_render_pass, 0);
|
||||
gpb.AddVertexBuffer(0, sizeof(ImDrawVert), VK_VERTEX_INPUT_RATE_VERTEX);
|
||||
@@ -2319,9 +2315,6 @@ void GSDeviceVK::RenderImGui()
|
||||
m_dirty_flags |= DIRTY_FLAG_UTILITY_TEXTURE;
|
||||
}
|
||||
|
||||
// imgui uses 16-bit indices
|
||||
SetIndexBuffer(m_index_stream_buffer.GetBuffer(), 0, VK_INDEX_TYPE_UINT16);
|
||||
|
||||
// this is for presenting, we don't want to screw with the viewport/scissor set by display
|
||||
m_dirty_flags &= ~(DIRTY_FLAG_VIEWPORT | DIRTY_FLAG_SCISSOR);
|
||||
|
||||
@@ -2343,19 +2336,8 @@ void GSDeviceVK::RenderImGui()
|
||||
m_vertex_stream_buffer.CommitMemory(size);
|
||||
}
|
||||
|
||||
u32 index_offset;
|
||||
{
|
||||
const u32 size = sizeof(ImDrawIdx) * static_cast<u32>(cmd_list->IdxBuffer.Size);
|
||||
if (!m_index_stream_buffer.ReserveMemory(size, sizeof(ImDrawIdx)))
|
||||
{
|
||||
Console.Warning("Skipping ImGui draw because of no vertex buffer space");
|
||||
return;
|
||||
}
|
||||
|
||||
index_offset = m_index_stream_buffer.GetCurrentOffset() / sizeof(ImDrawIdx);
|
||||
std::memcpy(m_index_stream_buffer.GetCurrentHostPointer(), cmd_list->IdxBuffer.Data, size);
|
||||
m_index_stream_buffer.CommitMemory(size);
|
||||
}
|
||||
static_assert(sizeof(ImDrawIdx) == sizeof(u16));
|
||||
IASetIndexBuffer(cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size);
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
@@ -2366,7 +2348,7 @@ void GSDeviceVK::RenderImGui()
|
||||
if ((clip.zwzw() <= clip.xyxy()).mask() != 0)
|
||||
continue;
|
||||
|
||||
SetScissor(GSVector4i(clip));
|
||||
SetScissor(GSVector4i(clip).max_i32(GSVector4i::zero()));
|
||||
|
||||
// Since we don't have the GSTexture...
|
||||
Vulkan::Texture* tex = static_cast<Vulkan::Texture*>(pcmd->GetTexID());
|
||||
@@ -2379,7 +2361,7 @@ void GSDeviceVK::RenderImGui()
|
||||
if (ApplyUtilityState())
|
||||
{
|
||||
vkCmdDrawIndexed(g_vulkan_context->GetCurrentCommandBuffer(), pcmd->ElemCount, 1,
|
||||
index_offset + pcmd->IdxOffset, vertex_offset + pcmd->VtxOffset, 0);
|
||||
m_index.start + pcmd->IdxOffset, vertex_offset + pcmd->VtxOffset, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2655,6 +2637,7 @@ VkPipeline GSDeviceVK::CreateTFXPipeline(const PipelineSelector& p)
|
||||
return VK_NULL_HANDLE;
|
||||
|
||||
Vulkan::GraphicsPipelineBuilder gpb;
|
||||
SetPipelineProvokingVertex(m_features, gpb);
|
||||
|
||||
// Common state
|
||||
gpb.SetPipelineLayout(m_tfx_pipeline_layout);
|
||||
@@ -2739,14 +2722,11 @@ VkPipeline GSDeviceVK::CreateTFXPipeline(const PipelineSelector& p)
|
||||
VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, p.cms.wrgba);
|
||||
}
|
||||
|
||||
if (m_features.provoking_vertex_last)
|
||||
gpb.SetProvokingVertex(VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT);
|
||||
|
||||
// Tests have shown that it's faster to just enable rast order on the entire pass, rather than alternating
|
||||
// between turning it on and off for different draws, and adding the required barrier between non-rast-order
|
||||
// and rast-order draws.
|
||||
if (m_features.framebuffer_fetch && p.IsRTFeedbackLoop())
|
||||
gpb.AddBlendFlags(VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_ARM);
|
||||
gpb.AddBlendFlags(VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT);
|
||||
|
||||
VkPipeline pipeline = gpb.Create(g_vulkan_context->GetDevice(), g_vulkan_shader_cache->GetPipelineCache(true));
|
||||
if (pipeline)
|
||||
@@ -2786,7 +2766,7 @@ void GSDeviceVK::InitializeState()
|
||||
m_vertex_buffer_offset = 0;
|
||||
m_index_buffer = m_index_stream_buffer.GetBuffer();
|
||||
m_index_buffer_offset = 0;
|
||||
m_index_type = VK_INDEX_TYPE_UINT32;
|
||||
m_index_type = VK_INDEX_TYPE_UINT16;
|
||||
m_current_framebuffer = VK_NULL_HANDLE;
|
||||
m_current_render_pass = VK_NULL_HANDLE;
|
||||
|
||||
@@ -2864,7 +2844,12 @@ void GSDeviceVK::ExecuteCommandBufferAndRestartRenderPass(bool wait_for_completi
|
||||
Console.Warning("Vulkan: Executing command buffer due to '%s'", reason);
|
||||
|
||||
const VkRenderPass render_pass = m_current_render_pass;
|
||||
const GSVector4i render_pass_area(m_current_render_pass_area);
|
||||
const GSVector4i render_pass_area = m_current_render_pass_area;
|
||||
const GSVector4i scissor = m_scissor;
|
||||
GSTexture* const current_rt = m_current_render_target;
|
||||
GSTexture* const current_ds = m_current_depth_target;
|
||||
const FeedbackLoopFlag current_feedback_loop = m_current_framebuffer_feedback_loop;
|
||||
|
||||
EndRenderPass();
|
||||
g_vulkan_context->ExecuteCommandBuffer(GetWaitType(wait_for_completion, GSConfig.HWSpinCPUForReadbacks));
|
||||
InvalidateCachedState();
|
||||
@@ -2872,8 +2857,7 @@ void GSDeviceVK::ExecuteCommandBufferAndRestartRenderPass(bool wait_for_completi
|
||||
if (render_pass != VK_NULL_HANDLE)
|
||||
{
|
||||
// rebind framebuffer
|
||||
ApplyBaseState(m_dirty_flags, g_vulkan_context->GetCurrentCommandBuffer());
|
||||
m_dirty_flags &= ~DIRTY_BASE_STATE;
|
||||
OMSetRenderTargets(current_rt, current_ds, scissor, current_feedback_loop);
|
||||
|
||||
// restart render pass
|
||||
BeginRenderPass(render_pass, render_pass_area);
|
||||
@@ -2906,6 +2890,15 @@ void GSDeviceVK::InvalidateCachedState()
|
||||
m_dirty_flags |= DIRTY_FLAG_VERTEX_BUFFER;
|
||||
if (m_index_buffer != VK_NULL_HANDLE)
|
||||
m_dirty_flags |= DIRTY_FLAG_INDEX_BUFFER;
|
||||
|
||||
for (u32 i = 0; i < NUM_TFX_TEXTURES; i++)
|
||||
m_tfx_textures[i] = &m_null_texture;
|
||||
m_utility_texture = &m_null_texture;
|
||||
m_current_framebuffer = VK_NULL_HANDLE;
|
||||
m_current_render_target = nullptr;
|
||||
m_current_depth_target = nullptr;
|
||||
m_current_framebuffer_feedback_loop = FeedbackLoopFlag_None;
|
||||
|
||||
m_current_pipeline_layout = PipelineLayout::Undefined;
|
||||
m_tfx_descriptor_sets[1] = VK_NULL_HANDLE;
|
||||
m_tfx_descriptor_sets[2] = VK_NULL_HANDLE;
|
||||
@@ -3113,9 +3106,10 @@ void GSDeviceVK::EndRenderPass()
|
||||
if (m_current_render_pass == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
vkCmdEndRenderPass(g_vulkan_context->GetCurrentCommandBuffer());
|
||||
|
||||
m_current_render_pass = VK_NULL_HANDLE;
|
||||
g_perfmon.Put(GSPerfMon::RenderPasses, 1);
|
||||
|
||||
vkCmdEndRenderPass(g_vulkan_context->GetCurrentCommandBuffer());
|
||||
}
|
||||
|
||||
void GSDeviceVK::SetViewport(const VkViewport& viewport)
|
||||
@@ -3648,13 +3642,19 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
(!hdr_rt && DATE_rp != DATE_RENDER_PASS_STENCIL_ONE && CheckRenderPassArea(render_area));
|
||||
|
||||
// render pass restart optimizations
|
||||
if (render_area_okay)
|
||||
if (render_area_okay && (m_current_render_target == draw_rt || m_current_depth_target == draw_ds))
|
||||
{
|
||||
// avoid restarting the render pass just to switch from rt+depth to rt and vice versa
|
||||
if (!draw_ds && m_current_depth_target && m_current_render_target == draw_rt &&
|
||||
config.tex != m_current_depth_target && m_current_depth_target->GetSize() == draw_rt->GetSize() &&
|
||||
((pipe.feedback_loop_flags & FeedbackLoopFlag_ReadAndWriteRT) ==
|
||||
(m_current_framebuffer_feedback_loop & FeedbackLoopFlag_ReadAndWriteRT)))
|
||||
// keep the depth even if doing HDR draws, because the next draw will probably re-enable depth
|
||||
if (!draw_rt && m_current_render_target && config.tex != m_current_render_target &&
|
||||
m_current_render_target->GetSize() == draw_ds->GetSize())
|
||||
{
|
||||
draw_rt = m_current_render_target;
|
||||
m_pipeline_selector.rt = true;
|
||||
m_pipeline_selector.cms.wrgba = 0;
|
||||
}
|
||||
else if (!draw_ds && m_current_depth_target && config.tex != m_current_depth_target &&
|
||||
m_current_depth_target->GetSize() == draw_rt->GetSize())
|
||||
{
|
||||
draw_ds = m_current_depth_target;
|
||||
m_pipeline_selector.ds = true;
|
||||
@@ -3663,9 +3663,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
|
||||
// Prefer keeping feedback loop enabled, that way we're not constantly restarting render passes
|
||||
pipe.feedback_loop_flags |= (m_current_render_target == draw_rt && m_current_depth_target == draw_ds) ?
|
||||
m_current_framebuffer_feedback_loop :
|
||||
0;
|
||||
pipe.feedback_loop_flags |= m_current_framebuffer_feedback_loop;
|
||||
}
|
||||
|
||||
// We don't need the very first barrier if this is the first draw after switching to feedback loop,
|
||||
@@ -3833,7 +3831,8 @@ void GSDeviceVK::UpdateHWPipelineSelector(GSHWDrawConfig& config, PipelineSelect
|
||||
(config.ps.IsFeedbackLoop() || config.require_one_barrier || config.require_full_barrier)) ?
|
||||
FeedbackLoopFlag_ReadAndWriteRT :
|
||||
FeedbackLoopFlag_None;
|
||||
pipe.feedback_loop_flags |= (config.tex == config.ds) ? FeedbackLoopFlag_ReadDS : FeedbackLoopFlag_None;
|
||||
pipe.feedback_loop_flags |=
|
||||
(config.tex && config.tex == config.ds) ? FeedbackLoopFlag_ReadDS : FeedbackLoopFlag_None;
|
||||
|
||||
// enable point size in the vertex shader if we're rendering points regardless of upscaling.
|
||||
pipe.vs.point_size |= (config.topology == GSHWDrawConfig::Topology::Point);
|
||||
@@ -3847,7 +3846,7 @@ void GSDeviceVK::UploadHWDrawVerticesAndIndices(const GSHWDrawConfig& config)
|
||||
{
|
||||
m_index.start = 0;
|
||||
m_index.count = config.nindices;
|
||||
SetIndexBuffer(m_expand_index_buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
SetIndexBuffer(m_expand_index_buffer, 0, VK_INDEX_TYPE_UINT16);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -316,6 +316,7 @@ __fi void vif1Interrupt()
|
||||
CPU_INT(DMAC_VIF1, 128);
|
||||
if (gifRegs.stat.APATH == 3)
|
||||
vif1Regs.stat.VGW = 1; //We're waiting for path 3. Gunslinger II
|
||||
CPU_SET_DMASTALL(DMAC_VIF1, true);
|
||||
return;
|
||||
}
|
||||
vif1Regs.stat.VGW = 0; //Path 3 isn't busy so we don't need to wait for it.
|
||||
|
||||
@@ -83,7 +83,10 @@ static __fi void vuExecMicro(int idx, u32 addr, bool requires_wait)
|
||||
|
||||
vifFlush(idx);
|
||||
if (GetVifX.waitforvu)
|
||||
{
|
||||
CPU_SET_DMASTALL(idx ? DMAC_VIF1 : DMAC_VIF0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vifRegs.itops > (idx ? 0x3ffu : 0xffu))
|
||||
{
|
||||
@@ -220,7 +223,10 @@ vifOp(vifCode_Flush)
|
||||
}
|
||||
|
||||
if (vif1.waitforvu || vif1Regs.stat.VGW)
|
||||
{
|
||||
CPU_SET_DMASTALL(DMAC_VIF1, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vif1.cmd = 0;
|
||||
vif1.pass = 0;
|
||||
@@ -250,7 +256,10 @@ vifOp(vifCode_FlushA)
|
||||
}
|
||||
|
||||
if (vif1.waitforvu || vif1Regs.stat.VGW)
|
||||
{
|
||||
CPU_SET_DMASTALL(DMAC_VIF1, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vif1.cmd = 0;
|
||||
vif1.pass = 0;
|
||||
@@ -268,7 +277,10 @@ vifOp(vifCode_FlushE)
|
||||
vifFlush(idx);
|
||||
|
||||
if (vifX.waitforvu)
|
||||
{
|
||||
CPU_SET_DMASTALL(idx ? DMAC_VIF1 : DMAC_VIF0, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vifX.cmd = 0;
|
||||
vifX.pass = 0;
|
||||
@@ -373,7 +385,10 @@ vifOp(vifCode_MPG)
|
||||
vifFlush(idx);
|
||||
|
||||
if (vifX.waitforvu)
|
||||
{
|
||||
CPU_SET_DMASTALL(idx ? DMAC_VIF1 : DMAC_VIF0, true);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vifX.pass = 1;
|
||||
@@ -418,7 +433,10 @@ vifOp(vifCode_MSCAL)
|
||||
vifFlush(idx);
|
||||
|
||||
if (vifX.waitforvu)
|
||||
{
|
||||
CPU_SET_DMASTALL(idx ? DMAC_VIF1 : DMAC_VIF0, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vuExecMicro(idx, (u16)(vifXRegs.code), false);
|
||||
vifX.cmd = 0;
|
||||
@@ -454,7 +472,10 @@ vifOp(vifCode_MSCALF)
|
||||
}
|
||||
|
||||
if (vifX.waitforvu || vif1Regs.stat.VGW)
|
||||
{
|
||||
CPU_SET_DMASTALL(idx ? DMAC_VIF1 : DMAC_VIF0, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vuExecMicro(idx, (u16)(vifXRegs.code), true);
|
||||
vifX.cmd = 0;
|
||||
@@ -473,7 +494,10 @@ vifOp(vifCode_MSCNT)
|
||||
vifFlush(idx);
|
||||
|
||||
if (vifX.waitforvu)
|
||||
{
|
||||
CPU_SET_DMASTALL(idx ? DMAC_VIF1 : DMAC_VIF0, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vuExecMicro(idx, -1, false);
|
||||
vifX.cmd = 0;
|
||||
|
||||
@@ -311,7 +311,6 @@
|
||||
<ClCompile Include="GS\Renderers\SW\GSTextureSW.cpp" />
|
||||
<ClCompile Include="GS\GSUtil.cpp" />
|
||||
<ClCompile Include="GS\GSVector.cpp" />
|
||||
<ClCompile Include="GS\Renderers\Common\GSVertexList.cpp" />
|
||||
<ClCompile Include="GS\Renderers\SW\GSVertexSW.cpp" />
|
||||
<ClCompile Include="GS\Renderers\Common\GSVertexTrace.cpp" />
|
||||
<ClCompile Include="GS\Renderers\Common\GSVertexTraceFMM.cpp" />
|
||||
@@ -646,7 +645,6 @@
|
||||
<ClInclude Include="GS\GSVector8.h" />
|
||||
<ClInclude Include="GS\Renderers\Common\GSVertex.h" />
|
||||
<ClInclude Include="GS\Renderers\HW\GSVertexHW.h" />
|
||||
<ClInclude Include="GS\Renderers\Common\GSVertexList.h" />
|
||||
<ClInclude Include="GS\Renderers\SW\GSVertexSW.h" />
|
||||
<ClInclude Include="GS\Renderers\Common\GSVertexTrace.h" />
|
||||
<ClInclude Include="GS\GSXXH.h" />
|
||||
|
||||
@@ -1133,9 +1133,6 @@
|
||||
<ClCompile Include="GS\Renderers\Common\GSVertexTraceFMM.cpp">
|
||||
<Filter>System\Ps2\GS\Renderers\Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GS\Renderers\Common\GSVertexList.cpp">
|
||||
<Filter>System\Ps2\GS\Renderers\Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GS\Renderers\Common\GSFunctionMap.cpp">
|
||||
<Filter>System\Ps2\GS\Renderers\Common</Filter>
|
||||
</ClCompile>
|
||||
@@ -2020,9 +2017,6 @@
|
||||
<ClInclude Include="GS\Renderers\Common\GSVertexTrace.h">
|
||||
<Filter>System\Ps2\GS\Renderers\Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GS\Renderers\Common\GSVertexList.h">
|
||||
<Filter>System\Ps2\GS\Renderers\Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GS\Renderers\Common\GSVertex.h">
|
||||
<Filter>System\Ps2\GS\Renderers\Common</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@@ -1015,6 +1015,9 @@ public:
|
||||
microMapGPR& mapI = gprMap[i];
|
||||
if (mapI.VIreg == viLoadReg)
|
||||
{
|
||||
// Do this first, there is a case where when loadReg != writeReg, the findFreeGPR can steal the loadReg
|
||||
gprMap[i].count = this_counter;
|
||||
|
||||
if (viWriteReg >= 0) // Reg will be modified
|
||||
{
|
||||
if (viLoadReg != viWriteReg)
|
||||
@@ -1025,7 +1028,17 @@ public:
|
||||
// allocate a new register for writing to
|
||||
int x = findFreeGPR(viWriteReg);
|
||||
const xRegister32& gprX = xRegister32::GetInstance(x);
|
||||
|
||||
writeBackReg(gprX, true);
|
||||
|
||||
// writeReg not cached, needs backing up
|
||||
if (backup && gprMap[x].VIreg != viWriteReg)
|
||||
{
|
||||
xMOVZX(gprX, ptr16[&getVI(viWriteReg)]);
|
||||
writeVIBackup(gprX);
|
||||
backup = false;
|
||||
}
|
||||
|
||||
if (zext_if_dirty)
|
||||
xMOVZX(gprX, xRegister16(i));
|
||||
else
|
||||
@@ -1048,7 +1061,7 @@ public:
|
||||
xMOVZX(xRegister32(i), xRegister16(i));
|
||||
gprMap[i].isZeroExtended = true;
|
||||
}
|
||||
gprMap[i].count = this_counter;
|
||||
|
||||
gprMap[i].isNeeded = true;
|
||||
|
||||
if (backup)
|
||||
|
||||
@@ -24,7 +24,7 @@ import functools
|
||||
|
||||
src_dirs = [os.path.join(os.path.dirname(__file__), "..", "pcsx2"), os.path.join(os.path.dirname(__file__), "..", "pcsx2-qt")]
|
||||
fa_file = os.path.join(os.path.dirname(__file__), "..", "3rdparty", "include", "IconsFontAwesome5.h")
|
||||
dst_file = os.path.join(os.path.dirname(__file__), "..", "pcsx2", "Frontend", "ImguiManager.cpp")
|
||||
dst_file = os.path.join(os.path.dirname(__file__), "..", "pcsx2", "Frontend", "ImGuiManager.cpp")
|
||||
|
||||
all_source_files = list(functools.reduce(lambda prev, src_dir: prev + glob.glob(os.path.join(src_dir, "**", "*.cpp"), recursive=True) + \
|
||||
glob.glob(os.path.join(src_dir, "**", "*.h"), recursive=True) + \
|
||||
|
||||