summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/input.h5
-rw-r--r--src/common/settings.h2
-rw-r--r--src/core/core_timing.cpp4
-rw-r--r--src/core/frontend/framebuffer_layout.cpp2
-rw-r--r--src/core/frontend/framebuffer_layout.h1
-rw-r--r--src/core/hid/input_converter.cpp10
-rw-r--r--src/core/hle/result.h119
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp14
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.h1
-rw-r--r--src/core/hle/service/friend/friend.cpp13
-rw-r--r--src/core/hle/service/nfp/nfp_types.h2
-rw-r--r--src/input_common/input_poller.cpp10
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h34
-rw-r--r--src/video_core/dirty_flags.cpp24
-rw-r--r--src/video_core/engines/maxwell_3d.cpp328
-rw-r--r--src/video_core/engines/maxwell_3d.h3843
-rw-r--r--src/video_core/gpu.h50
-rw-r--r--src/video_core/host1x/syncpoint_manager.cpp12
-rw-r--r--src/video_core/macro/macro_hle.cpp48
-rw-r--r--src/video_core/query_cache.h2
-rw-r--r--src/video_core/renderer_base.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_graphics_pipeline.cpp29
-rw-r--r--src/video_core/renderer_opengl/gl_graphics_pipeline.h4
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp141
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp43
-rw-r--r--src/video_core/renderer_opengl/gl_state_tracker.cpp53
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h287
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.cpp303
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.h15
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp337
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp14
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp67
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp96
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.cpp6
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp84
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.h3
-rw-r--r--src/video_core/renderer_vulkan/vk_state_tracker.cpp50
-rw-r--r--src/video_core/shader_cache.cpp12
-rw-r--r--src/video_core/shader_environment.cpp23
-rw-r--r--src/video_core/shader_environment.h2
-rw-r--r--src/video_core/surface.cpp14
-rw-r--r--src/video_core/texture_cache/image_info.cpp37
-rw-r--r--src/video_core/texture_cache/texture_cache.h19
-rw-r--r--src/video_core/transform_feedback.cpp118
-rw-r--r--src/video_core/transform_feedback.h3
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp7
-rw-r--r--src/yuzu/configuration/configure_graphics.ui5
-rw-r--r--src/yuzu/main.cpp16
49 files changed, 4209 insertions, 2113 deletions
diff --git a/src/common/input.h b/src/common/input.h
index bfa0639f5..b533f3844 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -277,8 +277,9 @@ struct CallbackStatus {
BodyColorStatus color_status{};
BatteryStatus battery_status{};
VibrationStatus vibration_status{};
- CameraStatus camera_status{};
- NfcStatus nfc_status{};
+ CameraFormat camera_status{CameraFormat::None};
+ NfcState nfc_status{NfcState::Unknown};
+ std::vector<u8> raw_data{};
};
// Triggered once every input change
diff --git a/src/common/settings.h b/src/common/settings.h
index d2452c93b..0eb98939c 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -431,7 +431,7 @@ struct Values {
FullscreenMode::Exclusive,
#endif
FullscreenMode::Borderless, FullscreenMode::Exclusive, "fullscreen_mode"};
- SwitchableSetting<int, true> aspect_ratio{0, 0, 3, "aspect_ratio"};
+ SwitchableSetting<int, true> aspect_ratio{0, 0, 4, "aspect_ratio"};
SwitchableSetting<int, true> max_anisotropy{0, 0, 5, "max_anisotropy"};
SwitchableSetting<bool> use_speed_limit{true, "use_speed_limit"};
SwitchableSetting<u16, true> speed_limit{100, 0, 9999, "speed_limit"};
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 6c0fcb7b5..2678ce532 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -270,6 +270,7 @@ void CoreTiming::ThreadLoop() {
// There are more events left in the queue, wait until the next event.
const auto wait_time = *next_time - GetGlobalTimeNs().count();
if (wait_time > 0) {
+#ifdef _WIN32
// Assume a timer resolution of 1ms.
static constexpr s64 TimerResolutionNS = 1000000;
@@ -287,6 +288,9 @@ void CoreTiming::ThreadLoop() {
if (event.IsSet()) {
event.Reset();
}
+#else
+ event.WaitFor(std::chrono::nanoseconds(wait_time));
+#endif
}
} else {
// Queue is empty, wait until another event is scheduled and signals us to continue.
diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp
index 90dd68ff1..b4081fc39 100644
--- a/src/core/frontend/framebuffer_layout.cpp
+++ b/src/core/frontend/framebuffer_layout.cpp
@@ -67,6 +67,8 @@ float EmulationAspectRatio(AspectRatio aspect, float window_aspect_ratio) {
return 3.0f / 4.0f;
case AspectRatio::R21_9:
return 9.0f / 21.0f;
+ case AspectRatio::R16_10:
+ return 10.0f / 16.0f;
case AspectRatio::StretchToWindow:
return window_aspect_ratio;
default:
diff --git a/src/core/frontend/framebuffer_layout.h b/src/core/frontend/framebuffer_layout.h
index 1561d994e..94683b30f 100644
--- a/src/core/frontend/framebuffer_layout.h
+++ b/src/core/frontend/framebuffer_layout.h
@@ -27,6 +27,7 @@ enum class AspectRatio {
Default,
R4_3,
R21_9,
+ R16_10,
StretchToWindow,
};
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index fe9915abe..5d8b75b50 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -277,7 +277,10 @@ Common::Input::CameraStatus TransformToCamera(const Common::Input::CallbackStatu
Common::Input::CameraStatus camera{};
switch (callback.type) {
case Common::Input::InputType::IrSensor:
- camera = callback.camera_status;
+ camera = {
+ .format = callback.camera_status,
+ .data = callback.raw_data,
+ };
break;
default:
LOG_ERROR(Input, "Conversion from type {} to camera not implemented", callback.type);
@@ -291,7 +294,10 @@ Common::Input::NfcStatus TransformToNfc(const Common::Input::CallbackStatus& cal
Common::Input::NfcStatus nfc{};
switch (callback.type) {
case Common::Input::InputType::Nfc:
- return callback.nfc_status;
+ nfc = {
+ .state = callback.nfc_status,
+ .data = callback.raw_data,
+ };
break;
default:
LOG_ERROR(Input, "Conversion from type {} to NFC not implemented", callback.type);
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 47a1b829b..d67e68bae 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -5,6 +5,7 @@
#include "common/assert.h"
#include "common/bit_field.h"
+#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/expected.h"
@@ -130,6 +131,10 @@ union Result {
[[nodiscard]] constexpr bool IsError() const {
return !IsSuccess();
}
+
+ [[nodiscard]] constexpr bool IsFailure() const {
+ return !IsSuccess();
+ }
};
static_assert(std::is_trivial_v<Result>);
@@ -349,10 +354,109 @@ private:
} \
} while (false)
-#define R_SUCCEEDED(res) (res.IsSuccess())
+#define R_SUCCEEDED(res) (static_cast<Result>(res).IsSuccess())
+#define R_FAILED(res) (static_cast<Result>(res).IsFailure())
-/// Evaluates a boolean expression, and succeeds if that expression is true.
-#define R_SUCCEED_IF(expr) R_UNLESS(!(expr), ResultSuccess)
+namespace ResultImpl {
+template <auto EvaluateResult, class F>
+class ScopedResultGuard {
+ YUZU_NON_COPYABLE(ScopedResultGuard);
+ YUZU_NON_MOVEABLE(ScopedResultGuard);
+
+private:
+ Result& m_ref;
+ F m_f;
+
+public:
+ constexpr ScopedResultGuard(Result& ref, F f) : m_ref(ref), m_f(std::move(f)) {}
+ constexpr ~ScopedResultGuard() {
+ if (EvaluateResult(m_ref)) {
+ m_f();
+ }
+ }
+};
+
+template <auto EvaluateResult>
+class ResultReferenceForScopedResultGuard {
+private:
+ Result& m_ref;
+
+public:
+ constexpr ResultReferenceForScopedResultGuard(Result& r) : m_ref(r) {}
+ constexpr operator Result&() const {
+ return m_ref;
+ }
+};
+
+template <auto EvaluateResult, typename F>
+constexpr ScopedResultGuard<EvaluateResult, F> operator+(
+ ResultReferenceForScopedResultGuard<EvaluateResult> ref, F&& f) {
+ return ScopedResultGuard<EvaluateResult, F>(static_cast<Result&>(ref), std::forward<F>(f));
+}
+
+constexpr bool EvaluateResultSuccess(const Result& r) {
+ return R_SUCCEEDED(r);
+}
+constexpr bool EvaluateResultFailure(const Result& r) {
+ return R_FAILED(r);
+}
+
+template <typename T>
+constexpr void UpdateCurrentResultReference(T result_reference, Result result) = delete;
+// Intentionally not defined
+
+template <>
+constexpr void UpdateCurrentResultReference<Result&>(Result& result_reference, Result result) {
+ result_reference = result;
+}
+
+template <>
+constexpr void UpdateCurrentResultReference<const Result>(Result result_reference, Result result) {}
+} // namespace ResultImpl
+
+#define DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(COUNTER_VALUE) \
+ [[maybe_unused]] constexpr bool HasPrevRef_##COUNTER_VALUE = \
+ std::same_as<decltype(__TmpCurrentResultReference), Result&>; \
+ [[maybe_unused]] auto& PrevRef_##COUNTER_VALUE = __TmpCurrentResultReference; \
+ [[maybe_unused]] Result __tmp_result_##COUNTER_VALUE = ResultSuccess; \
+ Result& __TmpCurrentResultReference = \
+ HasPrevRef_##COUNTER_VALUE ? PrevRef_##COUNTER_VALUE : __tmp_result_##COUNTER_VALUE
+
+#define ON_RESULT_RETURN_IMPL(...) \
+ static_assert(std::same_as<decltype(__TmpCurrentResultReference), Result&>); \
+ auto RESULT_GUARD_STATE_##__COUNTER__ = \
+ ResultImpl::ResultReferenceForScopedResultGuard<__VA_ARGS__>( \
+ __TmpCurrentResultReference) + \
+ [&]()
+
+#define ON_RESULT_FAILURE_2 ON_RESULT_RETURN_IMPL(ResultImpl::EvaluateResultFailure)
+
+#define ON_RESULT_FAILURE \
+ DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(__COUNTER__); \
+ ON_RESULT_FAILURE_2
+
+#define ON_RESULT_SUCCESS_2 ON_RESULT_RETURN_IMPL(ResultImpl::EvaluateResultSuccess)
+
+#define ON_RESULT_SUCCESS \
+ DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(__COUNTER__); \
+ ON_RESULT_SUCCESS_2
+
+constexpr inline Result __TmpCurrentResultReference = ResultSuccess;
+
+/// Returns a result.
+#define R_RETURN(res_expr) \
+ { \
+ const Result _tmp_r_throw_rc = (res_expr); \
+ ResultImpl::UpdateCurrentResultReference<decltype(__TmpCurrentResultReference)>( \
+ __TmpCurrentResultReference, _tmp_r_throw_rc); \
+ return _tmp_r_throw_rc; \
+ }
+
+/// Returns ResultSuccess()
+#define R_SUCCEED() R_RETURN(ResultSuccess)
+
+/// Throws a result.
+#define R_THROW(res_expr) R_RETURN(res_expr)
/// Evaluates a boolean expression, and returns a result unless that expression is true.
#define R_UNLESS(expr, res) \
@@ -361,7 +465,7 @@ private:
if (res.IsError()) { \
LOG_ERROR(Kernel, "Failed with result: {}", res.raw); \
} \
- return res; \
+ R_THROW(res); \
} \
}
@@ -369,7 +473,10 @@ private:
#define R_TRY(res_expr) \
{ \
const auto _tmp_r_try_rc = (res_expr); \
- if (_tmp_r_try_rc.IsError()) { \
- return _tmp_r_try_rc; \
+ if (R_FAILED(_tmp_r_try_rc)) { \
+ R_THROW(_tmp_r_try_rc); \
} \
}
+
+/// Evaluates a boolean expression, and succeeds if that expression is true.
+#define R_SUCCEED_IF(expr) R_UNLESS(!(expr), ResultSuccess)
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index e23eae36a..c08274ef9 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -707,7 +707,7 @@ FSP_SRV::FSP_SRV(Core::System& system_)
{31, nullptr, "OpenGameCardFileSystem"},
{32, nullptr, "ExtendSaveDataFileSystem"},
{33, nullptr, "DeleteCacheStorage"},
- {34, nullptr, "GetCacheStorageSize"},
+ {34, &FSP_SRV::GetCacheStorageSize, "GetCacheStorageSize"},
{35, nullptr, "CreateSaveDataFileSystemByHashSalt"},
{36, nullptr, "OpenHostFileSystemWithOption"},
{51, &FSP_SRV::OpenSaveDataFileSystem, "OpenSaveDataFileSystem"},
@@ -1107,6 +1107,18 @@ void FSP_SRV::GetProgramIndexForAccessLog(Kernel::HLERequestContext& ctx) {
rb.Push(access_log_program_index);
}
+void FSP_SRV::GetCacheStorageSize(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto index{rp.Pop<s32>()};
+
+ LOG_WARNING(Service_FS, "(STUBBED) called with index={}", index);
+
+ IPC::ResponseBuilder rb{ctx, 6};
+ rb.Push(ResultSuccess);
+ rb.Push(s64{0});
+ rb.Push(s64{0});
+}
+
class IMultiCommitManager final : public ServiceFramework<IMultiCommitManager> {
public:
explicit IMultiCommitManager(Core::System& system_)
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h
index 36f552e05..3d88b97f9 100644
--- a/src/core/hle/service/filesystem/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp_srv.h
@@ -54,6 +54,7 @@ private:
void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx);
void GetProgramIndexForAccessLog(Kernel::HLERequestContext& ctx);
void OpenMultiCommitManager(Kernel::HLERequestContext& ctx);
+ void GetCacheStorageSize(Kernel::HLERequestContext& ctx);
FileSystemController& fsc;
const FileSys::ContentProvider& content_provider;
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index e0db787fc..fad532115 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -26,7 +26,7 @@ public:
{10101, &IFriendService::GetFriendList, "GetFriendList"},
{10102, nullptr, "UpdateFriendInfo"},
{10110, nullptr, "GetFriendProfileImage"},
- {10120, nullptr, "IsFriendListCacheAvailable"},
+ {10120, &IFriendService::CheckFriendListAvailability, "CheckFriendListAvailability"},
{10121, nullptr, "EnsureFriendListAvailable"},
{10200, nullptr, "SendFriendRequestForApplication"},
{10211, nullptr, "AddFacedFriendRequestForApplication"},
@@ -194,6 +194,17 @@ private:
// TODO(ogniK): Return a buffer of u64s which are the "NetworkServiceAccountId"
}
+ void CheckFriendListAvailability(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto uuid{rp.PopRaw<Common::UUID>()};
+
+ LOG_WARNING(Service_Friend, "(STUBBED) called, uuid=0x{}", uuid.RawString());
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(true);
+ }
+
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* completion_event;
diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h
index 867ea2f36..c09f9ddb6 100644
--- a/src/core/hle/service/nfp/nfp_types.h
+++ b/src/core/hle/service/nfp/nfp_types.h
@@ -167,7 +167,7 @@ struct AmiiboDate {
bool IsValidDate() const {
const bool is_day_valid = GetDay() > 0 && GetDay() < 32;
- const bool is_month_valid = GetMonth() >= 0 && GetMonth() < 13;
+ const bool is_month_valid = GetMonth() > 0 && GetMonth() < 13;
const bool is_year_valid = GetYear() >= 2000;
return is_year_valid && is_month_valid && is_day_valid;
}
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
index 75705b67e..ca33fb4eb 100644
--- a/src/input_common/input_poller.cpp
+++ b/src/input_common/input_poller.cpp
@@ -691,9 +691,12 @@ public:
}
void OnChange() {
+ const auto camera_status = GetStatus();
+
const Common::Input::CallbackStatus status{
.type = Common::Input::InputType::IrSensor,
- .camera_status = GetStatus(),
+ .camera_status = camera_status.format,
+ .raw_data = camera_status.data,
};
TriggerOnChange(status);
@@ -732,9 +735,12 @@ public:
}
void OnChange() {
+ const auto nfc_status = GetStatus();
+
const Common::Input::CallbackStatus status{
.type = Common::Input::InputType::Nfc,
- .nfc_status = GetStatus(),
+ .nfc_status = nfc_status.state,
+ .raw_data = nfc_status.data,
};
TriggerOnChange(status);
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 8e26b3f95..2ba33543c 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -994,13 +994,13 @@ void BufferCache<P>::BindHostIndexBuffer() {
const u32 size = index_buffer.size;
SynchronizeBuffer(buffer, index_buffer.cpu_addr, size);
if constexpr (HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) {
- const u32 new_offset = offset + maxwell3d->regs.index_array.first *
- maxwell3d->regs.index_array.FormatSizeInBytes();
+ const u32 new_offset = offset + maxwell3d->regs.index_buffer.first *
+ maxwell3d->regs.index_buffer.FormatSizeInBytes();
runtime.BindIndexBuffer(buffer, new_offset, size);
} else {
- runtime.BindIndexBuffer(maxwell3d->regs.draw.topology, maxwell3d->regs.index_array.format,
- maxwell3d->regs.index_array.first,
- maxwell3d->regs.index_array.count, buffer, offset, size);
+ runtime.BindIndexBuffer(maxwell3d->regs.draw.topology, maxwell3d->regs.index_buffer.format,
+ maxwell3d->regs.index_buffer.first,
+ maxwell3d->regs.index_buffer.count, buffer, offset, size);
}
}
@@ -1017,7 +1017,7 @@ void BufferCache<P>::BindHostVertexBuffers() {
}
flags[Dirty::VertexBuffer0 + index] = false;
- const u32 stride = maxwell3d->regs.vertex_array[index].stride;
+ const u32 stride = maxwell3d->regs.vertex_streams[index].stride;
const u32 offset = buffer.Offset(binding.cpu_addr);
runtime.BindVertexBuffer(index, buffer, offset, binding.size, stride);
}
@@ -1157,7 +1157,7 @@ void BufferCache<P>::BindHostGraphicsTextureBuffers(size_t stage) {
template <class P>
void BufferCache<P>::BindHostTransformFeedbackBuffers() {
- if (maxwell3d->regs.tfb_enabled == 0) {
+ if (maxwell3d->regs.transform_feedback_enabled == 0) {
return;
}
for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) {
@@ -1268,7 +1268,7 @@ template <class P>
void BufferCache<P>::UpdateIndexBuffer() {
// We have to check for the dirty flags and index count
// The index count is currently changed without updating the dirty flags
- const auto& index_array = maxwell3d->regs.index_array;
+ const auto& index_array = maxwell3d->regs.index_buffer;
auto& flags = maxwell3d->dirty.flags;
if (!flags[Dirty::IndexBuffer] && last_index_count == index_array.count) {
return;
@@ -1311,10 +1311,10 @@ void BufferCache<P>::UpdateVertexBuffer(u32 index) {
if (!maxwell3d->dirty.flags[Dirty::VertexBuffer0 + index]) {
return;
}
- const auto& array = maxwell3d->regs.vertex_array[index];
- const auto& limit = maxwell3d->regs.vertex_array_limit[index];
- const GPUVAddr gpu_addr_begin = array.StartAddress();
- const GPUVAddr gpu_addr_end = limit.LimitAddress() + 1;
+ const auto& array = maxwell3d->regs.vertex_streams[index];
+ const auto& limit = maxwell3d->regs.vertex_stream_limits[index];
+ const GPUVAddr gpu_addr_begin = array.Address();
+ const GPUVAddr gpu_addr_end = limit.Address() + 1;
const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr_begin);
u32 address_size = static_cast<u32>(
std::min(gpu_addr_end - gpu_addr_begin, static_cast<u64>(std::numeric_limits<u32>::max())));
@@ -1380,7 +1380,7 @@ void BufferCache<P>::UpdateTextureBuffers(size_t stage) {
template <class P>
void BufferCache<P>::UpdateTransformFeedbackBuffers() {
- if (maxwell3d->regs.tfb_enabled == 0) {
+ if (maxwell3d->regs.transform_feedback_enabled == 0) {
return;
}
for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) {
@@ -1390,11 +1390,11 @@ void BufferCache<P>::UpdateTransformFeedbackBuffers() {
template <class P>
void BufferCache<P>::UpdateTransformFeedbackBuffer(u32 index) {
- const auto& binding = maxwell3d->regs.tfb_bindings[index];
- const GPUVAddr gpu_addr = binding.Address() + binding.buffer_offset;
- const u32 size = binding.buffer_size;
+ const auto& binding = maxwell3d->regs.transform_feedback.buffers[index];
+ const GPUVAddr gpu_addr = binding.Address() + binding.start_offset;
+ const u32 size = binding.size;
const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
- if (binding.buffer_enable == 0 || size == 0 || !cpu_addr) {
+ if (binding.enable == 0 || size == 0 || !cpu_addr) {
transform_feedback_buffers[index] = NULL_BINDING;
return;
}
diff --git a/src/video_core/dirty_flags.cpp b/src/video_core/dirty_flags.cpp
index 9dc4341f0..c2ecc12f5 100644
--- a/src/video_core/dirty_flags.cpp
+++ b/src/video_core/dirty_flags.cpp
@@ -17,21 +17,23 @@ using Tegra::Engines::Maxwell3D;
void SetupDirtyVertexBuffers(Maxwell3D::DirtyState::Tables& tables) {
static constexpr std::size_t num_array = 3;
for (std::size_t i = 0; i < Maxwell3D::Regs::NumVertexArrays; ++i) {
- const std::size_t array_offset = OFF(vertex_array) + i * NUM(vertex_array[0]);
- const std::size_t limit_offset = OFF(vertex_array_limit) + i * NUM(vertex_array_limit[0]);
+ const std::size_t array_offset = OFF(vertex_streams) + i * NUM(vertex_streams[0]);
+ const std::size_t limit_offset =
+ OFF(vertex_stream_limits) + i * NUM(vertex_stream_limits[0]);
FillBlock(tables, array_offset, num_array, VertexBuffer0 + i, VertexBuffers);
- FillBlock(tables, limit_offset, NUM(vertex_array_limit), VertexBuffer0 + i, VertexBuffers);
+ FillBlock(tables, limit_offset, NUM(vertex_stream_limits), VertexBuffer0 + i,
+ VertexBuffers);
}
}
void SetupIndexBuffer(Maxwell3D::DirtyState::Tables& tables) {
- FillBlock(tables[0], OFF(index_array), NUM(index_array), IndexBuffer);
+ FillBlock(tables[0], OFF(index_buffer), NUM(index_buffer), IndexBuffer);
}
void SetupDirtyDescriptors(Maxwell3D::DirtyState::Tables& tables) {
- FillBlock(tables[0], OFF(tic), NUM(tic), Descriptors);
- FillBlock(tables[0], OFF(tsc), NUM(tsc), Descriptors);
+ FillBlock(tables[0], OFF(tex_header), NUM(tex_header), Descriptors);
+ FillBlock(tables[0], OFF(tex_sampler), NUM(tex_sampler), Descriptors);
}
void SetupDirtyRenderTargets(Maxwell3D::DirtyState::Tables& tables) {
@@ -42,7 +44,7 @@ void SetupDirtyRenderTargets(Maxwell3D::DirtyState::Tables& tables) {
FillBlock(tables[0], begin + rt * num_per_rt, num_per_rt, ColorBuffer0 + rt);
}
FillBlock(tables[1], begin, num, RenderTargets);
- FillBlock(tables[0], OFF(render_area), NUM(render_area), RenderTargets);
+ FillBlock(tables[0], OFF(surface_clip), NUM(surface_clip), RenderTargets);
tables[0][OFF(rt_control)] = RenderTargets;
tables[1][OFF(rt_control)] = RenderTargetControl;
@@ -52,15 +54,15 @@ void SetupDirtyRenderTargets(Maxwell3D::DirtyState::Tables& tables) {
const u8 flag = zeta_flags[i];
auto& table = tables[i];
table[OFF(zeta_enable)] = flag;
- table[OFF(zeta_width)] = flag;
- table[OFF(zeta_height)] = flag;
+ table[OFF(zeta_size.width)] = flag;
+ table[OFF(zeta_size.height)] = flag;
FillBlock(table, OFF(zeta), NUM(zeta), flag);
}
}
void SetupDirtyShaders(Maxwell3D::DirtyState::Tables& tables) {
- FillBlock(tables[0], OFF(shader_config[0]),
- NUM(shader_config[0]) * Maxwell3D::Regs::MaxShaderProgram, Shaders);
+ FillBlock(tables[0], OFF(pipelines), NUM(pipelines[0]) * Maxwell3D::Regs::MaxShaderProgram,
+ Shaders);
}
} // Anonymous namespace
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 3c6e44a25..89a9d1f5a 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -56,37 +56,37 @@ void Maxwell3D::InitializeRegisterDefaults() {
// Doom and Bomberman seems to use the uninitialized registers and just enable blend
// so initialize blend registers with sane values
- regs.blend.equation_rgb = Regs::Blend::Equation::Add;
- regs.blend.factor_source_rgb = Regs::Blend::Factor::One;
- regs.blend.factor_dest_rgb = Regs::Blend::Factor::Zero;
- regs.blend.equation_a = Regs::Blend::Equation::Add;
- regs.blend.factor_source_a = Regs::Blend::Factor::One;
- regs.blend.factor_dest_a = Regs::Blend::Factor::Zero;
- for (auto& blend : regs.independent_blend) {
- blend.equation_rgb = Regs::Blend::Equation::Add;
- blend.factor_source_rgb = Regs::Blend::Factor::One;
- blend.factor_dest_rgb = Regs::Blend::Factor::Zero;
- blend.equation_a = Regs::Blend::Equation::Add;
- blend.factor_source_a = Regs::Blend::Factor::One;
- blend.factor_dest_a = Regs::Blend::Factor::Zero;
- }
- regs.stencil_front_op_fail = Regs::StencilOp::Keep;
- regs.stencil_front_op_zfail = Regs::StencilOp::Keep;
- regs.stencil_front_op_zpass = Regs::StencilOp::Keep;
- regs.stencil_front_func_func = Regs::ComparisonOp::Always;
+ regs.blend.color_op = Regs::Blend::Equation::Add_D3D;
+ regs.blend.color_source = Regs::Blend::Factor::One_D3D;
+ regs.blend.color_dest = Regs::Blend::Factor::Zero_D3D;
+ regs.blend.alpha_op = Regs::Blend::Equation::Add_D3D;
+ regs.blend.alpha_source = Regs::Blend::Factor::One_D3D;
+ regs.blend.alpha_dest = Regs::Blend::Factor::Zero_D3D;
+ for (auto& blend : regs.blend_per_target) {
+ blend.color_op = Regs::Blend::Equation::Add_D3D;
+ blend.color_source = Regs::Blend::Factor::One_D3D;
+ blend.color_dest = Regs::Blend::Factor::Zero_D3D;
+ blend.alpha_op = Regs::Blend::Equation::Add_D3D;
+ blend.alpha_source = Regs::Blend::Factor::One_D3D;
+ blend.alpha_dest = Regs::Blend::Factor::Zero_D3D;
+ }
+ regs.stencil_front_op.fail = Regs::StencilOp::Op::Keep_D3D;
+ regs.stencil_front_op.zfail = Regs::StencilOp::Op::Keep_D3D;
+ regs.stencil_front_op.zpass = Regs::StencilOp::Op::Keep_D3D;
+ regs.stencil_front_op.func = Regs::ComparisonOp::Always_GL;
regs.stencil_front_func_mask = 0xFFFFFFFF;
regs.stencil_front_mask = 0xFFFFFFFF;
regs.stencil_two_side_enable = 1;
- regs.stencil_back_op_fail = Regs::StencilOp::Keep;
- regs.stencil_back_op_zfail = Regs::StencilOp::Keep;
- regs.stencil_back_op_zpass = Regs::StencilOp::Keep;
- regs.stencil_back_func_func = Regs::ComparisonOp::Always;
+ regs.stencil_back_op.fail = Regs::StencilOp::Op::Keep_D3D;
+ regs.stencil_back_op.zfail = Regs::StencilOp::Op::Keep_D3D;
+ regs.stencil_back_op.zpass = Regs::StencilOp::Op::Keep_D3D;
+ regs.stencil_back_op.func = Regs::ComparisonOp::Always_GL;
regs.stencil_back_func_mask = 0xFFFFFFFF;
regs.stencil_back_mask = 0xFFFFFFFF;
- regs.depth_test_func = Regs::ComparisonOp::Always;
- regs.front_face = Regs::FrontFace::CounterClockWise;
- regs.cull_face = Regs::CullFace::Back;
+ regs.depth_test_func = Regs::ComparisonOp::Always_GL;
+ regs.gl_front_face = Regs::FrontFace::CounterClockWise;
+ regs.gl_cull_face = Regs::CullFace::Back;
// TODO(Rodrigo): Most games do not set a point size. I think this is a case of a
// register carrying a default value. Assume it's OpenGL's default (1).
@@ -107,20 +107,20 @@ void Maxwell3D::InitializeRegisterDefaults() {
// NVN games expect these values to be enabled at boot
regs.rasterize_enable = 1;
- regs.rt_separate_frag_data = 1;
+ regs.color_target_mrt_enable = 1;
regs.framebuffer_srgb = 1;
regs.line_width_aliased = 1.0f;
regs.line_width_smooth = 1.0f;
- regs.front_face = Maxwell3D::Regs::FrontFace::ClockWise;
+ regs.gl_front_face = Maxwell3D::Regs::FrontFace::ClockWise;
regs.polygon_mode_back = Maxwell3D::Regs::PolygonMode::Fill;
regs.polygon_mode_front = Maxwell3D::Regs::PolygonMode::Fill;
shadow_state = regs;
- mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_end_gl)] = true;
- mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_begin_gl)] = true;
+ mme_inline[MAXWELL3D_REG_INDEX(draw.end)] = true;
+ mme_inline[MAXWELL3D_REG_INDEX(draw.begin)] = true;
mme_inline[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true;
- mme_inline[MAXWELL3D_REG_INDEX(index_array.count)] = true;
+ mme_inline[MAXWELL3D_REG_INDEX(index_buffer.count)] = true;
}
void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) {
@@ -173,51 +173,56 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume
case MAXWELL3D_REG_INDEX(shadow_ram_control):
shadow_state.shadow_ram_control = static_cast<Regs::ShadowRamControl>(nonshadow_argument);
return;
- case MAXWELL3D_REG_INDEX(macros.upload_address):
- return macro_engine->ClearCode(regs.macros.upload_address);
- case MAXWELL3D_REG_INDEX(macros.data):
- return macro_engine->AddCode(regs.macros.upload_address, argument);
- case MAXWELL3D_REG_INDEX(macros.bind):
+ case MAXWELL3D_REG_INDEX(load_mme.instruction_ptr):
+ return macro_engine->ClearCode(regs.load_mme.instruction_ptr);
+ case MAXWELL3D_REG_INDEX(load_mme.instruction):
+ return macro_engine->AddCode(regs.load_mme.instruction_ptr, argument);
+ case MAXWELL3D_REG_INDEX(load_mme.start_address):
return ProcessMacroBind(argument);
- case MAXWELL3D_REG_INDEX(firmware[4]):
+ case MAXWELL3D_REG_INDEX(falcon[4]):
return ProcessFirmwareCall4();
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data):
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 1:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 2:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 3:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 4:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 5:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 6:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 7:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 8:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 9:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 10:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 11:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 12:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 13:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 14:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 15:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer):
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 1:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 2:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 3:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 4:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 5:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 6:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 7:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 8:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 9:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 10:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 11:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 12:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 13:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 14:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 15:
return ProcessCBData(argument);
- case MAXWELL3D_REG_INDEX(cb_bind[0]):
+ case MAXWELL3D_REG_INDEX(bind_groups[0].raw_config):
return ProcessCBBind(0);
- case MAXWELL3D_REG_INDEX(cb_bind[1]):
+ case MAXWELL3D_REG_INDEX(bind_groups[1].raw_config):
return ProcessCBBind(1);
- case MAXWELL3D_REG_INDEX(cb_bind[2]):
+ case MAXWELL3D_REG_INDEX(bind_groups[2].raw_config):
return ProcessCBBind(2);
- case MAXWELL3D_REG_INDEX(cb_bind[3]):
+ case MAXWELL3D_REG_INDEX(bind_groups[3].raw_config):
return ProcessCBBind(3);
- case MAXWELL3D_REG_INDEX(cb_bind[4]):
+ case MAXWELL3D_REG_INDEX(bind_groups[4].raw_config):
return ProcessCBBind(4);
- case MAXWELL3D_REG_INDEX(draw.vertex_end_gl):
+ case MAXWELL3D_REG_INDEX(draw.end):
return DrawArrays();
- case MAXWELL3D_REG_INDEX(small_index):
- regs.index_array.count = regs.small_index.count;
- regs.index_array.first = regs.small_index.first;
+ case MAXWELL3D_REG_INDEX(index_buffer32_first):
+ regs.index_buffer.count = regs.index_buffer32_first.count;
+ regs.index_buffer.first = regs.index_buffer32_first.first;
dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
return DrawArrays();
- case MAXWELL3D_REG_INDEX(small_index_2):
- regs.index_array.count = regs.small_index_2.count;
- regs.index_array.first = regs.small_index_2.first;
+ case MAXWELL3D_REG_INDEX(index_buffer16_first):
+ regs.index_buffer.count = regs.index_buffer16_first.count;
+ regs.index_buffer.first = regs.index_buffer16_first.first;
+ dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
+ return DrawArrays();
+ case MAXWELL3D_REG_INDEX(index_buffer8_first):
+ regs.index_buffer.count = regs.index_buffer8_first.count;
+ regs.index_buffer.first = regs.index_buffer8_first.first;
dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
// a macro calls this one over and over, should it increase instancing?
// Used by Hades and likely other Vulkan games.
@@ -225,28 +230,24 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume
case MAXWELL3D_REG_INDEX(topology_override):
use_topology_override = true;
return;
- case MAXWELL3D_REG_INDEX(clear_buffers):
+ case MAXWELL3D_REG_INDEX(clear_surface):
return ProcessClearBuffers();
- case MAXWELL3D_REG_INDEX(query.query_get):
+ case MAXWELL3D_REG_INDEX(report_semaphore.query):
return ProcessQueryGet();
- case MAXWELL3D_REG_INDEX(condition.mode):
+ case MAXWELL3D_REG_INDEX(render_enable.mode):
return ProcessQueryCondition();
- case MAXWELL3D_REG_INDEX(counter_reset):
+ case MAXWELL3D_REG_INDEX(clear_report_value):
return ProcessCounterReset();
case MAXWELL3D_REG_INDEX(sync_info):
return ProcessSyncPoint();
- case MAXWELL3D_REG_INDEX(exec_upload):
- return upload_state.ProcessExec(regs.exec_upload.linear != 0);
- case MAXWELL3D_REG_INDEX(data_upload):
+ case MAXWELL3D_REG_INDEX(launch_dma):
+ return upload_state.ProcessExec(regs.launch_dma.memory_layout.Value() ==
+ Regs::LaunchDMA::Layout::Pitch);
+ case MAXWELL3D_REG_INDEX(inline_data):
upload_state.ProcessData(argument, is_last_call);
return;
case MAXWELL3D_REG_INDEX(fragment_barrier):
return rasterizer->FragmentBarrier();
- case MAXWELL3D_REG_INDEX(invalidate_texture_data_cache):
- rasterizer->InvalidateGPUCache();
- return rasterizer->WaitForIdle();
- case MAXWELL3D_REG_INDEX(tiled_cache_barrier):
- return rasterizer->TiledCacheBarrier();
}
}
@@ -296,25 +297,25 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount,
return;
}
switch (method) {
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data):
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 1:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 2:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 3:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 4:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 5:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 6:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 7:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 8:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 9:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 10:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 11:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 12:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 13:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 14:
- case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 15:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer):
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 1:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 2:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 3:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 4:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 5:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 6:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 7:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 8:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 9:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 10:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 11:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 12:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 13:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 14:
+ case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 15:
ProcessCBMultiData(base_start, amount);
break;
- case MAXWELL3D_REG_INDEX(data_upload):
+ case MAXWELL3D_REG_INDEX(inline_data):
upload_state.ProcessData(base_start, static_cast<size_t>(amount));
return;
default:
@@ -353,14 +354,15 @@ void Maxwell3D::CallMethodFromMME(u32 method, u32 method_argument) {
if (mme_inline[method]) {
regs.reg_array[method] = method_argument;
if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count) ||
- method == MAXWELL3D_REG_INDEX(index_array.count)) {
+ method == MAXWELL3D_REG_INDEX(index_buffer.count)) {
const MMEDrawMode expected_mode = method == MAXWELL3D_REG_INDEX(vertex_buffer.count)
? MMEDrawMode::Array
: MMEDrawMode::Indexed;
StepInstance(expected_mode, method_argument);
- } else if (method == MAXWELL3D_REG_INDEX(draw.vertex_begin_gl)) {
+ } else if (method == MAXWELL3D_REG_INDEX(draw.begin)) {
mme_draw.instance_mode =
- (regs.draw.instance_next != 0) || (regs.draw.instance_cont != 0);
+ (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) ||
+ (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged);
mme_draw.gl_begin_consume = true;
} else {
mme_draw.gl_end_count++;
@@ -405,11 +407,12 @@ void Maxwell3D::ProcessTopologyOverride() {
void Maxwell3D::FlushMMEInlineDraw() {
LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(),
regs.vertex_buffer.count);
- ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?");
+ ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?");
ASSERT(mme_draw.instance_count == mme_draw.gl_end_count);
// Both instance configuration registers can not be set at the same time.
- ASSERT_MSG(!regs.draw.instance_next || !regs.draw.instance_cont,
+ ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First ||
+ regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
"Illegal combination of instancing parameters");
ProcessTopologyOverride();
@@ -424,7 +427,7 @@ void Maxwell3D::FlushMMEInlineDraw() {
// it's possible that it is incorrect and that there is some other register used to specify the
// drawing mode.
if (is_indexed) {
- regs.index_array.count = 0;
+ regs.index_buffer.count = 0;
} else {
regs.vertex_buffer.count = 0;
}
@@ -437,11 +440,11 @@ void Maxwell3D::FlushMMEInlineDraw() {
}
void Maxwell3D::ProcessMacroUpload(u32 data) {
- macro_engine->AddCode(regs.macros.upload_address++, data);
+ macro_engine->AddCode(regs.load_mme.instruction_ptr++, data);
}
void Maxwell3D::ProcessMacroBind(u32 data) {
- macro_positions[regs.macros.entry++] = data;
+ macro_positions[regs.load_mme.start_address_ptr++] = data;
}
void Maxwell3D::ProcessFirmwareCall4() {
@@ -449,11 +452,11 @@ void Maxwell3D::ProcessFirmwareCall4() {
// Firmware call 4 is a blob that changes some registers depending on its parameters.
// These registers don't affect emulation and so are stubbed by setting 0xd00 to 1.
- regs.reg_array[0xd00] = 1;
+ regs.shadow_scratch[0] = 1;
}
void Maxwell3D::StampQueryResult(u64 payload, bool long_query) {
- const GPUVAddr sequence_address{regs.query.QueryAddress()};
+ const GPUVAddr sequence_address{regs.report_semaphore.Address()};
if (long_query) {
memory_manager.Write<u64>(sequence_address + sizeof(u64), system.GPU().GetTicks());
memory_manager.Write<u64>(sequence_address, payload);
@@ -464,15 +467,17 @@ void Maxwell3D::StampQueryResult(u64 payload, bool long_query) {
void Maxwell3D::ProcessQueryGet() {
// TODO(Subv): Support the other query units.
- if (regs.query.query_get.unit != Regs::QueryUnit::Crop) {
- LOG_DEBUG(HW_GPU, "Units other than CROP are unimplemented");
+ if (regs.report_semaphore.query.location != Regs::ReportSemaphore::Location::All) {
+ LOG_DEBUG(HW_GPU, "Locations other than ALL are unimplemented");
}
- switch (regs.query.query_get.operation) {
- case Regs::QueryOperation::Release:
- if (regs.query.query_get.fence == 1 || regs.query.query_get.short_query != 0) {
- const GPUVAddr sequence_address{regs.query.QueryAddress()};
- const u32 payload = regs.query.query_sequence;
+ switch (regs.report_semaphore.query.operation) {
+ case Regs::ReportSemaphore::Operation::Release:
+ if (regs.report_semaphore.query.release ==
+ Regs::ReportSemaphore::Release::AfterAllPreceedingWrites ||
+ regs.report_semaphore.query.short_query != 0) {
+ const GPUVAddr sequence_address{regs.report_semaphore.Address()};
+ const u32 payload = regs.report_semaphore.payload;
std::function<void()> operation([this, sequence_address, payload] {
memory_manager.Write<u32>(sequence_address, payload);
});
@@ -482,8 +487,8 @@ void Maxwell3D::ProcessQueryGet() {
u64_le value;
u64_le timestamp;
};
- const GPUVAddr sequence_address{regs.query.QueryAddress()};
- const u32 payload = regs.query.query_sequence;
+ const GPUVAddr sequence_address{regs.report_semaphore.Address()};
+ const u32 payload = regs.report_semaphore.payload;
std::function<void()> operation([this, sequence_address, payload] {
memory_manager.Write<u64>(sequence_address + sizeof(u64), system.GPU().GetTicks());
memory_manager.Write<u64>(sequence_address, payload);
@@ -491,19 +496,19 @@ void Maxwell3D::ProcessQueryGet() {
rasterizer->SyncOperation(std::move(operation));
}
break;
- case Regs::QueryOperation::Acquire:
+ case Regs::ReportSemaphore::Operation::Acquire:
// TODO(Blinkhawk): Under this operation, the GPU waits for the CPU to write a value that
// matches the current payload.
UNIMPLEMENTED_MSG("Unimplemented query operation ACQUIRE");
break;
- case Regs::QueryOperation::Counter:
+ case Regs::ReportSemaphore::Operation::ReportOnly:
if (const std::optional<u64> result = GetQueryResult()) {
// If the query returns an empty optional it means it's cached and deferred.
// In this case we have a non-empty result, so we stamp it immediately.
- StampQueryResult(*result, regs.query.query_get.short_query == 0);
+ StampQueryResult(*result, regs.report_semaphore.query.short_query == 0);
}
break;
- case Regs::QueryOperation::Trap:
+ case Regs::ReportSemaphore::Operation::Trap:
UNIMPLEMENTED_MSG("Unimplemented query operation TRAP");
break;
default:
@@ -513,31 +518,31 @@ void Maxwell3D::ProcessQueryGet() {
}
void Maxwell3D::ProcessQueryCondition() {
- const GPUVAddr condition_address{regs.condition.Address()};
- switch (regs.condition.mode) {
- case Regs::ConditionMode::Always: {
+ const GPUVAddr condition_address{regs.render_enable.Address()};
+ switch (regs.render_enable.mode) {
+ case Regs::RenderEnable::Mode::True: {
execute_on = true;
break;
}
- case Regs::ConditionMode::Never: {
+ case Regs::RenderEnable::Mode::False: {
execute_on = false;
break;
}
- case Regs::ConditionMode::ResNonZero: {
- Regs::QueryCompare cmp;
+ case Regs::RenderEnable::Mode::Conditional: {
+ Regs::ReportSemaphore::Compare cmp;
memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
execute_on = cmp.initial_sequence != 0U && cmp.initial_mode != 0U;
break;
}
- case Regs::ConditionMode::Equal: {
- Regs::QueryCompare cmp;
+ case Regs::RenderEnable::Mode::IfEqual: {
+ Regs::ReportSemaphore::Compare cmp;
memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
execute_on =
cmp.initial_sequence == cmp.current_sequence && cmp.initial_mode == cmp.current_mode;
break;
}
- case Regs::ConditionMode::NotEqual: {
- Regs::QueryCompare cmp;
+ case Regs::RenderEnable::Mode::IfNotEqual: {
+ Regs::ReportSemaphore::Compare cmp;
memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
execute_on =
cmp.initial_sequence != cmp.current_sequence || cmp.initial_mode != cmp.current_mode;
@@ -552,21 +557,21 @@ void Maxwell3D::ProcessQueryCondition() {
}
void Maxwell3D::ProcessCounterReset() {
- switch (regs.counter_reset) {
- case Regs::CounterReset::SampleCnt:
+ switch (regs.clear_report_value) {
+ case Regs::ClearReport::ZPassPixelCount:
rasterizer->ResetCounter(QueryType::SamplesPassed);
break;
default:
- LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}", regs.counter_reset);
+ LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}", regs.clear_report_value);
break;
}
}
void Maxwell3D::ProcessSyncPoint() {
const u32 sync_point = regs.sync_info.sync_point.Value();
- const u32 increment = regs.sync_info.increment.Value();
- [[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value();
- if (increment) {
+ const auto condition = regs.sync_info.condition.Value();
+ [[maybe_unused]] const u32 cache_flush = regs.sync_info.clean_l2.Value();
+ if (condition == Regs::SyncInfo::Condition::RopWritesDone) {
rasterizer->SignalSyncPoint(sync_point);
}
}
@@ -574,23 +579,24 @@ void Maxwell3D::ProcessSyncPoint() {
void Maxwell3D::DrawArrays() {
LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(),
regs.vertex_buffer.count);
- ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?");
+ ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?");
// Both instance configuration registers can not be set at the same time.
- ASSERT_MSG(!regs.draw.instance_next || !regs.draw.instance_cont,
+ ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First ||
+ regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
"Illegal combination of instancing parameters");
ProcessTopologyOverride();
- if (regs.draw.instance_next) {
+ if (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) {
// Increment the current instance *before* drawing.
- state.current_instance += 1;
- } else if (!regs.draw.instance_cont) {
+ state.current_instance++;
+ } else if (regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged) {
// Reset the current instance to 0.
state.current_instance = 0;
}
- const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count};
+ const bool is_indexed{regs.index_buffer.count && !regs.vertex_buffer.count};
if (ShouldExecute()) {
rasterizer->Draw(is_indexed, false);
}
@@ -600,60 +606,60 @@ void Maxwell3D::DrawArrays() {
// it's possible that it is incorrect and that there is some other register used to specify the
// drawing mode.
if (is_indexed) {
- regs.index_array.count = 0;
+ regs.index_buffer.count = 0;
} else {
regs.vertex_buffer.count = 0;
}
}
std::optional<u64> Maxwell3D::GetQueryResult() {
- switch (regs.query.query_get.select) {
- case Regs::QuerySelect::Payload:
- return regs.query.query_sequence;
- case Regs::QuerySelect::SamplesPassed:
+ switch (regs.report_semaphore.query.report) {
+ case Regs::ReportSemaphore::Report::Payload:
+ return regs.report_semaphore.payload;
+ case Regs::ReportSemaphore::Report::ZPassPixelCount64:
// Deferred.
- rasterizer->Query(regs.query.QueryAddress(), QueryType::SamplesPassed,
+ rasterizer->Query(regs.report_semaphore.Address(), QueryType::SamplesPassed,
system.GPU().GetTicks());
return std::nullopt;
default:
- LOG_DEBUG(HW_GPU, "Unimplemented query select type {}",
- regs.query.query_get.select.Value());
+ LOG_DEBUG(HW_GPU, "Unimplemented query report type {}",
+ regs.report_semaphore.query.report.Value());
return 1;
}
}
void Maxwell3D::ProcessCBBind(size_t stage_index) {
// Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage.
- const auto& bind_data = regs.cb_bind[stage_index];
- auto& buffer = state.shader_stages[stage_index].const_buffers[bind_data.index];
+ const auto& bind_data = regs.bind_groups[stage_index];
+ auto& buffer = state.shader_stages[stage_index].const_buffers[bind_data.shader_slot];
buffer.enabled = bind_data.valid.Value() != 0;
- buffer.address = regs.const_buffer.BufferAddress();
- buffer.size = regs.const_buffer.cb_size;
+ buffer.address = regs.const_buffer.Address();
+ buffer.size = regs.const_buffer.size;
const bool is_enabled = bind_data.valid.Value() != 0;
if (!is_enabled) {
- rasterizer->DisableGraphicsUniformBuffer(stage_index, bind_data.index);
+ rasterizer->DisableGraphicsUniformBuffer(stage_index, bind_data.shader_slot);
return;
}
- const GPUVAddr gpu_addr = regs.const_buffer.BufferAddress();
- const u32 size = regs.const_buffer.cb_size;
- rasterizer->BindGraphicsUniformBuffer(stage_index, bind_data.index, gpu_addr, size);
+ const GPUVAddr gpu_addr = regs.const_buffer.Address();
+ const u32 size = regs.const_buffer.size;
+ rasterizer->BindGraphicsUniformBuffer(stage_index, bind_data.shader_slot, gpu_addr, size);
}
void Maxwell3D::ProcessCBMultiData(const u32* start_base, u32 amount) {
// Write the input value to the current const buffer at the current position.
- const GPUVAddr buffer_address = regs.const_buffer.BufferAddress();
+ const GPUVAddr buffer_address = regs.const_buffer.Address();
ASSERT(buffer_address != 0);
// Don't allow writing past the end of the buffer.
- ASSERT(regs.const_buffer.cb_pos <= regs.const_buffer.cb_size);
+ ASSERT(regs.const_buffer.offset <= regs.const_buffer.size);
- const GPUVAddr address{buffer_address + regs.const_buffer.cb_pos};
+ const GPUVAddr address{buffer_address + regs.const_buffer.offset};
const size_t copy_size = amount * sizeof(u32);
memory_manager.WriteBlock(address, start_base, copy_size);
// Increment the current buffer position.
- regs.const_buffer.cb_pos += static_cast<u32>(copy_size);
+ regs.const_buffer.offset += static_cast<u32>(copy_size);
}
void Maxwell3D::ProcessCBData(u32 value) {
@@ -661,7 +667,8 @@ void Maxwell3D::ProcessCBData(u32 value) {
}
Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
- const GPUVAddr tic_address_gpu{regs.tic.Address() + tic_index * sizeof(Texture::TICEntry)};
+ const GPUVAddr tic_address_gpu{regs.tex_header.Address() +
+ tic_index * sizeof(Texture::TICEntry)};
Texture::TICEntry tic_entry;
memory_manager.ReadBlockUnsafe(tic_address_gpu, &tic_entry, sizeof(Texture::TICEntry));
@@ -670,7 +677,8 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
}
Texture::TSCEntry Maxwell3D::GetTSCEntry(u32 tsc_index) const {
- const GPUVAddr tsc_address_gpu{regs.tsc.Address() + tsc_index * sizeof(Texture::TSCEntry)};
+ const GPUVAddr tsc_address_gpu{regs.tex_sampler.Address() +
+ tsc_index * sizeof(Texture::TSCEntry)};
Texture::TSCEntry tsc_entry;
memory_manager.ReadBlockUnsafe(tsc_address_gpu, &tsc_entry, sizeof(Texture::TSCEntry));
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 5f9eb208c..12dbd9cc4 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -39,12 +39,15 @@ namespace Tegra::Engines {
/**
* This Engine is known as GF100_3D. Documentation can be found in:
+ * https://github.com/NVIDIA/open-gpu-doc/blob/master/classes/3d/clb197.h
* https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml
* https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_3d.xml.h
+ *
+ * Note: nVidia have confirmed that their open docs have had parts redacted, so this list is
+ * currently incomplete, and the gaps are still worth exploring.
*/
-#define MAXWELL3D_REG_INDEX(field_name) \
- (offsetof(Tegra::Engines::Maxwell3D::Regs, field_name) / sizeof(u32))
+#define MAXWELL3D_REG_INDEX(field_name) (offsetof(Maxwell3D::Regs, field_name) / sizeof(u32))
class Maxwell3D final : public EngineInterface {
public:
@@ -55,7 +58,6 @@ public:
void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
/// Register structure of the Maxwell3D engine.
- /// TODO(Subv): This structure will need to be made bigger as more registers are discovered.
struct Regs {
static constexpr std::size_t NUM_REGS = 0xE00;
@@ -74,90 +76,515 @@ public:
static constexpr std::size_t MaxConstBuffers = 18;
static constexpr std::size_t MaxConstBufferSize = 0x10000;
- enum class QueryOperation : u32 {
- Release = 0,
- Acquire = 1,
- Counter = 2,
- Trap = 3,
+ struct ID {
+ union {
+ BitField<0, 16, u32> cls;
+ BitField<16, 5, u32> engine;
+ };
};
- enum class QueryUnit : u32 {
- VFetch = 1,
- VP = 2,
- Rast = 4,
- StrmOut = 5,
- GP = 6,
- ZCull = 7,
- Prop = 10,
- Crop = 15,
+ struct LoadMME {
+ u32 instruction_ptr;
+ u32 instruction;
+ u32 start_address_ptr;
+ u32 start_address;
};
- enum class QuerySelect : u32 {
- Payload = 0,
- TimeElapsed = 2,
- TransformFeedbackPrimitivesGenerated = 11,
- PrimitivesGenerated = 18,
- SamplesPassed = 21,
- TransformFeedbackUnknown = 26,
+ struct Notify {
+ u32 address_high;
+ u32 address_low;
+ u32 type;
+
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
};
- struct QueryCompare {
- u32 initial_sequence;
- u32 initial_mode;
- u32 unknown1;
- u32 unknown2;
- u32 current_sequence;
- u32 current_mode;
+ struct PeerSemaphore {
+ u32 address_high;
+ u32 address_low;
+
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
};
- enum class QuerySyncCondition : u32 {
- NotEqual = 0,
- GreaterThan = 1,
+ struct GlobalRender {
+ enum class Mode : u32 {
+ False = 0,
+ True = 1,
+ Conditional = 2,
+ IfEqual = 3,
+ IfNotEqual = 4,
+ };
+ u32 offset_high;
+ u32 offset_low;
+ Mode mode;
+
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(offset_high) << 32) |
+ offset_low);
+ }
};
- enum class ConditionMode : u32 {
- Never = 0,
- Always = 1,
- ResNonZero = 2,
- Equal = 3,
- NotEqual = 4,
+ enum class ReductionOp : u32 {
+ RedAdd = 0,
+ RedMin = 1,
+ RedMax = 2,
+ RedInc = 3,
+ RedDec = 4,
+ RedAnd = 5,
+ RedOr = 6,
+ RedXor = 7,
};
- enum class ShaderProgram : u32 {
- VertexA = 0,
- VertexB = 1,
- TesselationControl = 2,
- TesselationEval = 3,
- Geometry = 4,
- Fragment = 5,
+ struct LaunchDMA {
+ enum class Layout : u32 {
+ Blocklinear = 0,
+ Pitch = 1,
+ };
+
+ enum class CompletionType : u32 {
+ FlushDisable = 0,
+ FlushOnly = 1,
+ Release = 2,
+ };
+
+ union {
+ BitField<0, 1, Layout> memory_layout;
+ BitField<4, 2, CompletionType> completion_type;
+ BitField<8, 2, u32> interrupt_type;
+ BitField<12, 1, u32> sem_size;
+ BitField<1, 1, u32> reduction_enable;
+ BitField<13, 3, ReductionOp> reduction_op;
+ BitField<2, 2, u32> reduction_format;
+ BitField<6, 1, u32> sysmembar_disable;
+ };
+ };
+
+ struct I2M {
+ u32 address_high;
+ u32 address_low;
+ u32 payload;
+ INSERT_PADDING_BYTES_NOINIT(0x8);
+ u32 nop0;
+ u32 nop1;
+ u32 nop2;
+ u32 nop3;
+ };
+
+ struct OpportunisticEarlyZ {
+ BitField<0, 5, u32> threshold;
+
+ u32 Threshold() const {
+ switch (threshold) {
+ case 0x0:
+ return 0;
+ case 0x1F:
+ return 0x1F;
+ default:
+ // Thresholds begin at 0x10 (1 << 4)
+ // Threshold is in the range 0x1 to 0x13
+ return 1 << (4 + threshold.Value() - 1);
+ }
+ }
+ };
+
+ struct GeometryShaderDmFifo {
+ union {
+ BitField<0, 13, u32> raster_on;
+ BitField<16, 13, u32> raster_off;
+ BitField<31, 1, u32> spill_enabled;
+ };
+ };
+
+ struct L2CacheControl {
+ enum class EvictPolicy : u32 {
+ First = 0,
+ Normal = 1,
+ Last = 2,
+ };
+
+ union {
+ BitField<4, 2, EvictPolicy> policy;
+ };
+ };
+
+ struct InvalidateShaderCache {
+ union {
+ BitField<0, 1, u32> instruction;
+ BitField<4, 1, u32> data;
+ BitField<12, 1, u32> constant;
+ BitField<1, 1, u32> locks;
+ BitField<2, 1, u32> flush_data;
+ };
+ };
+
+ struct SyncInfo {
+ enum class Condition : u32 {
+ StreamOutWritesDone = 0,
+ RopWritesDone = 1,
+ };
+
+ union {
+ BitField<0, 16, u32> sync_point;
+ BitField<16, 1, u32> clean_l2;
+ BitField<20, 1, Condition> condition;
+ };
+ };
+
+ struct SurfaceClipBlockId {
+ union {
+ BitField<0, 4, u32> block_width;
+ BitField<4, 4, u32> block_height;
+ BitField<8, 4, u32> block_depth;
+ };
+ };
+
+ struct DecompressSurface {
+ union {
+ BitField<0, 3, u32> mrt_select;
+ BitField<4, 16, u32> rt_array_index;
+ };
+ };
+
+ struct ZCullRopBypass {
+ union {
+ BitField<0, 1, u32> enable;
+ BitField<4, 1, u32> no_stall;
+ BitField<8, 1, u32> cull_everything;
+ BitField<12, 4, u32> threshold;
+ };
+ };
+
+ struct ZCullSubregion {
+ union {
+ BitField<0, 1, u32> enable;
+ BitField<4, 24, u32> normalized_aliquots;
+ };
+ };
+
+ struct RasterBoundingBox {
+ enum class Mode : u32 {
+ BoundingBox = 0,
+ FullViewport = 1,
+ };
+
+ union {
+ BitField<0, 1, Mode> mode;
+ BitField<4, 8, u32> pad;
+ };
+ };
+
+ struct IteratedBlendOptimization {
+ enum class Noop : u32 {
+ Never = 0,
+ SourceRGBA0000 = 1,
+ SourceAlpha = 2,
+ SourceRGBA0001 = 3,
+ };
+
+ union {
+ BitField<0, 1, Noop> noop;
+ };
+ };
+
+ struct ZCullSubregionAllocation {
+ enum class Format : u32 {
+ Z_16x16x2_4x4 = 0,
+ ZS_16x16_4x4 = 1,
+ Z_16x16_4x2 = 2,
+ Z_16x16_2x4 = 3,
+ Z_16x8_4x4 = 4,
+ Z_8x8_4x2 = 5,
+ Z_8x8_2x4 = 6,
+ Z_16x16_4x8 = 7,
+ Z_4x8_2x2 = 8,
+ ZS_16x8_4x2 = 9,
+ ZS_16x8_2x4 = 10,
+ ZS_8x8_2x2 = 11,
+ Z_4x8_1x1 = 12,
+ None = 15,
+ };
+
+ union {
+ BitField<0, 8, u32> id;
+ BitField<8, 16, u32> aliquots;
+ BitField<24, 4, Format> format;
+ };
+ };
+
+ enum class ZCullSubregionAlgorithm : u32 {
+ Static = 0,
+ Adaptive = 1,
+ };
+
+ struct PixelShaderOutputSampleMaskUsage {
+ union {
+ BitField<0, 1, u32> enable;
+ BitField<1, 1, u32> qualify_by_aa;
+ };
+ };
+
+ struct L1Configuration {
+ enum class AddressableMemory : u32 {
+ Size16Kb = 0,
+ Size48Kb = 3,
+ };
+ union {
+ BitField<0, 3, AddressableMemory> direct_addressable_memory;
+ };
+ };
+
+ struct SPAVersion {
+ union {
+ BitField<0, 8, u32> minor;
+ BitField<8, 8, u32> major;
+ };
+ };
+
+ struct SnapGrid {
+ enum class Location : u32 {
+ Pixel2x2 = 1,
+ Pixel4x4 = 2,
+ Pixel8x8 = 3,
+ Pixel16x16 = 4,
+ Pixel32x32 = 5,
+ Pixel64x64 = 6,
+ Pixel128x128 = 7,
+ Pixel256x256 = 8,
+ };
+
+ enum class Mode : u32 {
+ RTNE = 0,
+ Tesla = 1,
+ };
+
+ struct {
+ union {
+ BitField<0, 4, Location> location;
+ BitField<8, 1, Mode> rounding_mode;
+ };
+ } line;
+
+ struct {
+ union {
+ BitField<0, 4, Location> location;
+ BitField<8, 1, Mode> rounding_mode;
+ };
+ } non_line;
+ };
+
+ struct Tessellation {
+ enum class DomainType : u32 {
+ Isolines = 0,
+ Triangles = 1,
+ Quads = 2,
+ };
+
+ enum class Spacing : u32 {
+ Integer = 0,
+ FractionalOdd = 1,
+ FractionalEven = 2,
+ };
+
+ enum class OutputPrimitves : u32 {
+ Points = 0,
+ Lines = 1,
+ Triangles_CW = 2,
+ Triangles_CCW = 3,
+ };
+
+ struct Parameters {
+ union {
+ BitField<0, 2, DomainType> domain_type;
+ BitField<4, 2, Spacing> spacing;
+ BitField<8, 2, OutputPrimitves> output_primitives;
+ };
+ } params;
+
+ struct LOD {
+ std::array<f32, 4> outer;
+ std::array<f32, 2> inner;
+ } lod;
+
+ std::array<u32, 9> reserved;
+ };
+
+ struct SubTilingPerf {
+ struct {
+ union {
+ BitField<0, 8, u32> spm_triangle_register_file_per;
+ BitField<8, 8, u32> spm_pixel_output_buffer_per;
+ BitField<16, 8, u32> spm_triangle_ram_per;
+ BitField<24, 8, u32> max_quads_per;
+ };
+ } knob_a;
+
+ struct {
+ union {
+ BitField<0, 8, u32> max_primitives_per;
+ };
+ } knob_b;
+
+ u32 knob_c;
+ };
+
+ struct ZCullSubregionReport {
+ enum class ReportType : u32 {
+ DepthTest = 0,
+ DepthTestNoAccept = 1,
+ DepthTestLateZ = 2,
+ StencilTest = 3,
+ };
+
+ union {
+ BitField<0, 1, u32> enabled;
+ BitField<4, 8, u32> subregion_id;
+ } to_report;
+
+ union {
+ BitField<0, 1, u32> enabled;
+ BitField<4, 3, ReportType> type;
+ } report_type;
+ };
+
+ struct BalancedPrimitiveWorkload {
+ union {
+ BitField<0, 1, u32> unpartitioned_mode;
+ BitField<4, 1, u32> timesliced_mode;
+ };
+ };
+
+ struct TransformFeedback {
+ struct Buffer {
+ u32 enable;
+ u32 address_high;
+ u32 address_low;
+ s32 size;
+ s32 start_offset;
+ INSERT_PADDING_BYTES_NOINIT(0xC);
+
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
+ };
+ static_assert(sizeof(Buffer) == 0x20);
+
+ struct Control {
+ u32 stream;
+ u32 varying_count;
+ u32 stride;
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ };
+ static_assert(sizeof(Control) == 0x10);
+
+ std::array<TransformFeedback::Buffer, NumTransformFeedbackBuffers> buffers;
+
+ INSERT_PADDING_BYTES_NOINIT(0x300);
+
+ std::array<TransformFeedback::Control, NumTransformFeedbackBuffers> controls;
+ };
+
+ struct HybridAntiAliasControl {
+ enum class Centroid : u32 {
+ PerFragment = 0,
+ PerPass = 1,
+ };
+ union {
+ BitField<0, 4, u32> passes;
+ BitField<4, 1, Centroid> centroid;
+ BitField<5, 1, u32> passes_extended;
+ };
+ };
+
+ struct ShaderLocalMemory {
+ u32 base_address;
+ INSERT_PADDING_BYTES_NOINIT(0x10);
+ u32 address_high;
+ u32 address_low;
+ u32 size_high;
+ u32 size_low;
+ u32 default_size_per_warp;
+
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
+
+ u64 Size() const {
+ return (static_cast<u64>(size_high) << 32) | size_low;
+ }
+ };
+
+ struct ZCullRegion {
+ u32 width;
+ u32 height;
+ u32 depth;
+ u32 offset;
+ INSERT_PADDING_BYTES_NOINIT(0xC);
+ u32 fetch_streams_once;
+ union {
+ BitField<0, 16, u32> start_aliquot;
+ BitField<16, 16, u32> aliquot_count;
+ } location;
+ u32 aliquots_per_layer;
+ u32 storage_address_high;
+ u32 storage_address_low;
+ u32 storage_limit_address_high;
+ u32 storage_limit_address_low;
+
+ GPUVAddr StorageAddress() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(storage_address_high) << 32) |
+ storage_address_low);
+ }
+ GPUVAddr StorageLimitAddress() const {
+ return static_cast<GPUVAddr>(
+ (static_cast<GPUVAddr>(storage_limit_address_high) << 32) |
+ storage_limit_address_low);
+ }
+ };
+
+ struct ZetaReadOnly {
+ union {
+ BitField<0, 1, u32> enable_z;
+ BitField<4, 1, u32> enable_stencil;
+ };
};
struct VertexAttribute {
enum class Size : u32 {
Invalid = 0x0,
- Size_32_32_32_32 = 0x01,
- Size_32_32_32 = 0x02,
- Size_16_16_16_16 = 0x03,
- Size_32_32 = 0x04,
- Size_16_16_16 = 0x05,
- Size_8_8_8_8 = 0x0a,
- Size_16_16 = 0x0f,
- Size_32 = 0x12,
- Size_8_8_8 = 0x13,
- Size_8_8 = 0x18,
- Size_16 = 0x1b,
- Size_8 = 0x1d,
- Size_10_10_10_2 = 0x30,
- Size_11_11_10 = 0x31,
+ Size_R32_G32_B32_A32 = 0x01,
+ Size_R32_G32_B32 = 0x02,
+ Size_R16_G16_B16_A16 = 0x03,
+ Size_R32_G32 = 0x04,
+ Size_R16_G16_B16 = 0x05,
+ Size_R8_G8_B8_A8 = 0x0A,
+ Size_R16_G16 = 0x0F,
+ Size_R32 = 0x12,
+ Size_R8_G8_B8 = 0x13,
+ Size_R8_G8 = 0x18,
+ Size_R16 = 0x1B,
+ Size_R8 = 0x1D,
+ Size_A2_B10_G10_R10 = 0x30,
+ Size_B10_G11_R11 = 0x31,
+ Size_G8_R8 = 0x32,
+ Size_X8_B8_G8_R8 = 0x33,
+ Size_A8 = 0x34,
};
enum class Type : u32 {
- SignedNorm = 1,
- UnsignedNorm = 2,
- SignedInt = 3,
- UnsignedInt = 4,
- UnsignedScaled = 5,
- SignedScaled = 6,
+ UnusedEnumDoNotUseBecauseItWillGoAway = 0,
+ SNorm = 1,
+ UNorm = 2,
+ SInt = 3,
+ UInt = 4,
+ UScaled = 5,
+ SScaled = 6,
Float = 7,
};
@@ -173,33 +600,36 @@ public:
u32 ComponentCount() const {
switch (size) {
- case Size::Size_32_32_32_32:
+ case Size::Size_R32_G32_B32_A32:
return 4;
- case Size::Size_32_32_32:
+ case Size::Size_R32_G32_B32:
return 3;
- case Size::Size_16_16_16_16:
+ case Size::Size_R16_G16_B16_A16:
return 4;
- case Size::Size_32_32:
+ case Size::Size_R32_G32:
return 2;
- case Size::Size_16_16_16:
+ case Size::Size_R16_G16_B16:
return 3;
- case Size::Size_8_8_8_8:
+ case Size::Size_R8_G8_B8_A8:
+ case Size::Size_X8_B8_G8_R8:
return 4;
- case Size::Size_16_16:
+ case Size::Size_R16_G16:
return 2;
- case Size::Size_32:
+ case Size::Size_R32:
return 1;
- case Size::Size_8_8_8:
+ case Size::Size_R8_G8_B8:
return 3;
- case Size::Size_8_8:
+ case Size::Size_R8_G8:
+ case Size::Size_G8_R8:
return 2;
- case Size::Size_16:
+ case Size::Size_R16:
return 1;
- case Size::Size_8:
+ case Size::Size_R8:
+ case Size::Size_A8:
return 1;
- case Size::Size_10_10_10_2:
+ case Size::Size_A2_B10_G10_R10:
return 4;
- case Size::Size_11_11_10:
+ case Size::Size_B10_G11_R11:
return 3;
default:
ASSERT(false);
@@ -209,33 +639,36 @@ public:
u32 SizeInBytes() const {
switch (size) {
- case Size::Size_32_32_32_32:
+ case Size::Size_R32_G32_B32_A32:
return 16;
- case Size::Size_32_32_32:
+ case Size::Size_R32_G32_B32:
return 12;
- case Size::Size_16_16_16_16:
+ case Size::Size_R16_G16_B16_A16:
return 8;
- case Size::Size_32_32:
+ case Size::Size_R32_G32:
return 8;
- case Size::Size_16_16_16:
+ case Size::Size_R16_G16_B16:
return 6;
- case Size::Size_8_8_8_8:
+ case Size::Size_R8_G8_B8_A8:
+ case Size::Size_X8_B8_G8_R8:
return 4;
- case Size::Size_16_16:
+ case Size::Size_R16_G16:
return 4;
- case Size::Size_32:
+ case Size::Size_R32:
return 4;
- case Size::Size_8_8_8:
+ case Size::Size_R8_G8_B8:
return 3;
- case Size::Size_8_8:
+ case Size::Size_R8_G8:
+ case Size::Size_G8_R8:
return 2;
- case Size::Size_16:
+ case Size::Size_R16:
return 2;
- case Size::Size_8:
+ case Size::Size_R8:
+ case Size::Size_A8:
return 1;
- case Size::Size_10_10_10_2:
+ case Size::Size_A2_B10_G10_R10:
return 4;
- case Size::Size_11_11_10:
+ case Size::Size_B10_G11_R11:
return 4;
default:
ASSERT(false);
@@ -245,34 +678,36 @@ public:
std::string SizeString() const {
switch (size) {
- case Size::Size_32_32_32_32:
+ case Size::Size_R32_G32_B32_A32:
return "32_32_32_32";
- case Size::Size_32_32_32:
+ case Size::Size_R32_G32_B32:
return "32_32_32";
- case Size::Size_16_16_16_16:
+ case Size::Size_R16_G16_B16_A16:
return "16_16_16_16";
- case Size::Size_32_32:
+ case Size::Size_R32_G32:
return "32_32";
- case Size::Size_16_16_16:
+ case Size::Size_R16_G16_B16:
return "16_16_16";
- case Size::Size_8_8_8_8:
+ case Size::Size_R8_G8_B8_A8:
return "8_8_8_8";
- case Size::Size_16_16:
+ case Size::Size_R16_G16:
return "16_16";
- case Size::Size_32:
+ case Size::Size_R32:
return "32";
- case Size::Size_8_8_8:
+ case Size::Size_R8_G8_B8:
return "8_8_8";
- case Size::Size_8_8:
+ case Size::Size_R8_G8:
+ case Size::Size_G8_R8:
return "8_8";
- case Size::Size_16:
+ case Size::Size_R16:
return "16";
- case Size::Size_8:
+ case Size::Size_R8:
+ case Size::Size_A8:
return "8";
- case Size::Size_10_10_10_2:
- return "10_10_10_2";
- case Size::Size_11_11_10:
- return "11_11_10";
+ case Size::Size_A2_B10_G10_R10:
+ return "2_10_10_10";
+ case Size::Size_B10_G11_R11:
+ return "10_11_12";
default:
ASSERT(false);
return {};
@@ -281,17 +716,19 @@ public:
std::string TypeString() const {
switch (type) {
- case Type::SignedNorm:
+ case Type::UnusedEnumDoNotUseBecauseItWillGoAway:
+ return "Unused";
+ case Type::SNorm:
return "SNORM";
- case Type::UnsignedNorm:
+ case Type::UNorm:
return "UNORM";
- case Type::SignedInt:
+ case Type::SInt:
return "SINT";
- case Type::UnsignedInt:
+ case Type::UInt:
return "UINT";
- case Type::UnsignedScaled:
+ case Type::UScaled:
return "USCALED";
- case Type::SignedScaled:
+ case Type::SScaled:
return "SSCALED";
case Type::Float:
return "FLOAT";
@@ -301,7 +738,7 @@ public:
}
bool IsNormalized() const {
- return (type == Type::SignedNorm) || (type == Type::UnsignedNorm);
+ return (type == Type::SNorm) || (type == Type::UNorm);
}
bool IsValid() const {
@@ -312,6 +749,7 @@ public:
return hex < other.hex;
}
};
+ static_assert(sizeof(VertexAttribute) == 0x4);
struct MsaaSampleLocation {
union {
@@ -342,9 +780,96 @@ public:
}
};
- enum class DepthMode : u32 {
- MinusOneToOne = 0,
- ZeroToOne = 1,
+ struct MultisampleCoverageToColor {
+ union {
+ BitField<0, 1, u32> enable;
+ BitField<4, 3, u32> target;
+ };
+ };
+
+ struct DecompressZetaSurface {
+ union {
+ BitField<0, 1, u32> z_enable;
+ BitField<4, 1, u32> stencil_enable;
+ };
+ };
+
+ struct ZetaSparse {
+ enum class UnmappedCompare : u32 {
+ Unmapped = 0,
+ FailAlways = 1,
+ };
+ union {
+ BitField<0, 1, u32> enable;
+ BitField<1, 1, UnmappedCompare> unmapped_compare;
+ };
+ };
+
+ struct RtControl {
+ union {
+ BitField<0, 4, u32> count;
+ BitField<4, 3, u32> target0;
+ BitField<7, 3, u32> target1;
+ BitField<10, 3, u32> target2;
+ BitField<13, 3, u32> target3;
+ BitField<16, 3, u32> target4;
+ BitField<19, 3, u32> target5;
+ BitField<22, 3, u32> target6;
+ BitField<25, 3, u32> target7;
+ };
+
+ u32 Map(std::size_t index) const {
+ const std::array<u32, NumRenderTargets> maps{target0, target1, target2, target3,
+ target4, target5, target6, target7};
+ ASSERT(index < maps.size());
+ return maps[index];
+ }
+ };
+
+ struct CompressionThresholdSamples {
+ u32 samples;
+
+ u32 Samples() {
+ if (samples == 0) {
+ return 0;
+ }
+ return 1 << (samples - 1);
+ }
+ };
+
+ struct PixelShaderInterlockControl {
+ enum class TileMode : u32 {
+ NoConflictDetect = 0,
+ DetectSampleConflict = 1,
+ DetectPixelConflict = 2,
+ };
+ enum class TileSize : u32 {
+ Size_16x16 = 0,
+ Size_8x8 = 1,
+ };
+ enum class FragmentOrder : u32 {
+ FragmentOrdered = 0,
+ FragmentUnordered = 1,
+ };
+ union {
+ BitField<0, 2, TileMode> tile_mode;
+ BitField<2, 1, TileSize> tile_size;
+ BitField<3, 1, FragmentOrder> fragment_order;
+ };
+ };
+
+ struct ZetaSize {
+ enum class DimensionControl : u32 {
+ DepthDefinesArray = 0,
+ ArraySizeOne = 1,
+ };
+
+ u32 width;
+ u32 height;
+ union {
+ BitField<0, 16, u32> depth;
+ BitField<16, 1, DimensionControl> dim_control;
+ };
};
enum class PrimitiveTopology : u32 {
@@ -358,15 +883,21 @@ public:
Quads = 0x7,
QuadStrip = 0x8,
Polygon = 0x9,
- LinesAdjacency = 0xa,
- LineStripAdjacency = 0xb,
- TrianglesAdjacency = 0xc,
- TriangleStripAdjacency = 0xd,
- Patches = 0xe,
+ LinesAdjacency = 0xA,
+ LineStripAdjacency = 0xB,
+ TrianglesAdjacency = 0xC,
+ TriangleStripAdjacency = 0xD,
+ Patches = 0xE,
+ };
+
+ struct VertexArray {
+ union {
+ BitField<0, 16, u32> start;
+ BitField<16, 12, u32> count;
+ BitField<28, 3, PrimitiveTopology> topology;
+ };
};
- // Constants as from NVC0_3D_UNK1970_D3D
- // https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/gallium/drivers/nouveau/nvc0/nvc0_3d.xml.h#L1598
enum class PrimitiveTopologyOverride : u32 {
None = 0x0,
Points = 0x1,
@@ -374,11 +905,32 @@ public:
LineStrip = 0x3,
Triangles = 0x4,
TriangleStrip = 0x5,
- LinesAdjacency = 0xa,
- LineStripAdjacency = 0xb,
- TrianglesAdjacency = 0xc,
- TriangleStripAdjacency = 0xd,
- Patches = 0xe,
+ LinesAdjacency = 0xA,
+ LineStripAdjacency = 0xB,
+ TrianglesAdjacency = 0xC,
+ TriangleStripAdjacency = 0xD,
+ Patches = 0xE,
+
+ LegacyPoints = 0x1001,
+ LegacyIndexedLines = 0x1002,
+ LegacyIndexedTriangles = 0x1003,
+ LegacyLines = 0x100F,
+ LegacyLineStrip = 0x1010,
+ LegacyIndexedLineStrip = 0x1011,
+ LegacyTriangles = 0x1012,
+ LegacyTriangleStrip = 0x1013,
+ LegacyIndexedTriangleStrip = 0x1014,
+ LegacyTriangleFan = 0x1015,
+ LegacyIndexedTriangleFan = 0x1016,
+ LegacyTriangleFanImm = 0x1017,
+ LegacyLinesImm = 0x1018,
+ LegacyIndexedTriangles2 = 0x101A,
+ LegacyIndexedLines2 = 0x101B,
+ };
+
+ enum class DepthMode : u32 {
+ MinusOneToOne = 0,
+ ZeroToOne = 1,
};
enum class IndexFormat : u32 {
@@ -388,183 +940,143 @@ public:
};
enum class ComparisonOp : u32 {
- // These values are used by Nouveau and most games, they correspond to the OpenGL token
- // values for these operations.
- Never = 0x200,
- Less = 0x201,
- Equal = 0x202,
- LessEqual = 0x203,
- Greater = 0x204,
- NotEqual = 0x205,
- GreaterEqual = 0x206,
- Always = 0x207,
-
- // These values are used by some games, they seem to be NV04 values.
- NeverOld = 1,
- LessOld = 2,
- EqualOld = 3,
- LessEqualOld = 4,
- GreaterOld = 5,
- NotEqualOld = 6,
- GreaterEqualOld = 7,
- AlwaysOld = 8,
- };
-
- enum class LogicOperation : u32 {
- Clear = 0x1500,
- And = 0x1501,
- AndReverse = 0x1502,
- Copy = 0x1503,
- AndInverted = 0x1504,
- NoOp = 0x1505,
- Xor = 0x1506,
- Or = 0x1507,
- Nor = 0x1508,
- Equiv = 0x1509,
- Invert = 0x150A,
- OrReverse = 0x150B,
- CopyInverted = 0x150C,
- OrInverted = 0x150D,
- Nand = 0x150E,
- Set = 0x150F,
- };
-
- enum class StencilOp : u32 {
- Keep = 1,
- Zero = 2,
- Replace = 3,
- Incr = 4,
- Decr = 5,
- Invert = 6,
- IncrWrap = 7,
- DecrWrap = 8,
- KeepOGL = 0x1E00,
- ZeroOGL = 0,
- ReplaceOGL = 0x1E01,
- IncrOGL = 0x1E02,
- DecrOGL = 0x1E03,
- InvertOGL = 0x150A,
- IncrWrapOGL = 0x8507,
- DecrWrapOGL = 0x8508,
- };
-
- enum class CounterReset : u32 {
- SampleCnt = 0x01,
- Unk02 = 0x02,
- Unk03 = 0x03,
- Unk04 = 0x04,
- EmittedPrimitives = 0x10, // Not tested
- Unk11 = 0x11,
- Unk12 = 0x12,
- Unk13 = 0x13,
- Unk15 = 0x15,
- Unk16 = 0x16,
- Unk17 = 0x17,
- Unk18 = 0x18,
- Unk1A = 0x1A,
- Unk1B = 0x1B,
- Unk1C = 0x1C,
- Unk1D = 0x1D,
- Unk1E = 0x1E,
- GeneratedPrimitives = 0x1F,
+ Never_D3D = 1,
+ Less_D3D = 2,
+ Equal_D3D = 3,
+ LessEqual_D3D = 4,
+ Greater_D3D = 5,
+ NotEqual_D3D = 6,
+ GreaterEqual_D3D = 7,
+ Always_D3D = 8,
+
+ Never_GL = 0x200,
+ Less_GL = 0x201,
+ Equal_GL = 0x202,
+ LessEqual_GL = 0x203,
+ Greater_GL = 0x204,
+ NotEqual_GL = 0x205,
+ GreaterEqual_GL = 0x206,
+ Always_GL = 0x207,
+ };
+
+ enum class ClearReport : u32 {
+ ZPassPixelCount = 0x01,
+ ZCullStats = 0x02,
+ StreamingPrimitvesNeededMinusSucceeded = 0x03,
+ AlphaBetaClocks = 0x04,
+ StreamingPrimitivesSucceeded = 0x10,
+ StreamingPrimitivesNeeded = 0x11,
+ VerticesGenerated = 0x12,
+ PrimitivesGenerated = 0x13,
+ VertexShaderInvocations = 0x15,
+ TessellationInitInvocations = 0x16,
+ TessellationShaderInvocations = 0x17,
+ TessellationShaderPrimitivesGenerated = 0x18,
+ GeometryShaderInvocations = 0x1A,
+ GeometryShaderPrimitivesGenerated = 0x1B,
+ ClipperInvocations = 0x1C,
+ ClipperPrimitivesGenerated = 0x1D,
+ PixelShaderInvocations = 0x1E,
+ VtgPrimitivesOut = 0x1F,
};
enum class FrontFace : u32 {
- ClockWise = 0x0900,
- CounterClockWise = 0x0901,
+ ClockWise = 0x900,
+ CounterClockWise = 0x901,
};
enum class CullFace : u32 {
- Front = 0x0404,
- Back = 0x0405,
- FrontAndBack = 0x0408,
+ Front = 0x404,
+ Back = 0x405,
+ FrontAndBack = 0x408,
};
struct Blend {
enum class Equation : u32 {
- Add = 1,
- Subtract = 2,
- ReverseSubtract = 3,
- Min = 4,
- Max = 5,
-
- // These values are used by Nouveau and some games.
- AddGL = 0x8006,
- MinGL = 0x8007,
- MaxGL = 0x8008,
- SubtractGL = 0x800a,
- ReverseSubtractGL = 0x800b
+ Add_D3D = 1,
+ Subtract_D3D = 2,
+ ReverseSubtract_D3D = 3,
+ Min_D3D = 4,
+ Max_D3D = 5,
+
+ Add_GL = 0x8006,
+ Min_GL = 0x8007,
+ Max_GL = 0x8008,
+ Subtract_GL = 0x800A,
+ ReverseSubtract_GL = 0x800B
};
enum class Factor : u32 {
- Zero = 0x1,
- One = 0x2,
- SourceColor = 0x3,
- OneMinusSourceColor = 0x4,
- SourceAlpha = 0x5,
- OneMinusSourceAlpha = 0x6,
- DestAlpha = 0x7,
- OneMinusDestAlpha = 0x8,
- DestColor = 0x9,
- OneMinusDestColor = 0xa,
- SourceAlphaSaturate = 0xb,
- Source1Color = 0x10,
- OneMinusSource1Color = 0x11,
- Source1Alpha = 0x12,
- OneMinusSource1Alpha = 0x13,
- ConstantColor = 0x61,
- OneMinusConstantColor = 0x62,
- ConstantAlpha = 0x63,
- OneMinusConstantAlpha = 0x64,
-
- // These values are used by Nouveau and some games.
- ZeroGL = 0x4000,
- OneGL = 0x4001,
- SourceColorGL = 0x4300,
- OneMinusSourceColorGL = 0x4301,
- SourceAlphaGL = 0x4302,
- OneMinusSourceAlphaGL = 0x4303,
- DestAlphaGL = 0x4304,
- OneMinusDestAlphaGL = 0x4305,
- DestColorGL = 0x4306,
- OneMinusDestColorGL = 0x4307,
- SourceAlphaSaturateGL = 0x4308,
- ConstantColorGL = 0xc001,
- OneMinusConstantColorGL = 0xc002,
- ConstantAlphaGL = 0xc003,
- OneMinusConstantAlphaGL = 0xc004,
- Source1ColorGL = 0xc900,
- OneMinusSource1ColorGL = 0xc901,
- Source1AlphaGL = 0xc902,
- OneMinusSource1AlphaGL = 0xc903,
+ Zero_D3D = 0x1,
+ One_D3D = 0x2,
+ SourceColor_D3D = 0x3,
+ OneMinusSourceColor_D3D = 0x4,
+ SourceAlpha_D3D = 0x5,
+ OneMinusSourceAlpha_D3D = 0x6,
+ DestAlpha_D3D = 0x7,
+ OneMinusDestAlpha_D3D = 0x8,
+ DestColor_D3D = 0x9,
+ OneMinusDestColor_D3D = 0xA,
+ SourceAlphaSaturate_D3D = 0xB,
+ BothSourceAlpha_D3D = 0xC,
+ OneMinusBothSourceAlpha_D3D = 0xD,
+ BlendFactor_D3D = 0xE,
+ OneMinusBlendFactor_D3D = 0xF,
+ Source1Color_D3D = 0x10,
+ OneMinusSource1Color_D3D = 0x11,
+ Source1Alpha_D3D = 0x12,
+ OneMinusSource1Alpha_D3D = 0x13,
+
+ Zero_GL = 0x4000,
+ One_GL = 0x4001,
+ SourceColor_GL = 0x4300,
+ OneMinusSourceColor_GL = 0x4301,
+ SourceAlpha_GL = 0x4302,
+ OneMinusSourceAlpha_GL = 0x4303,
+ DestAlpha_GL = 0x4304,
+ OneMinusDestAlpha_GL = 0x4305,
+ DestColor_GL = 0x4306,
+ OneMinusDestColor_GL = 0x4307,
+ SourceAlphaSaturate_GL = 0x4308,
+ ConstantColor_GL = 0xC001,
+ OneMinusConstantColor_GL = 0xC002,
+ ConstantAlpha_GL = 0xC003,
+ OneMinusConstantAlpha_GL = 0xC004,
+ Source1Color_GL = 0xC900,
+ OneMinusSource1Color_GL = 0xC901,
+ Source1Alpha_GL = 0xC902,
+ OneMinusSource1Alpha_GL = 0xC903,
};
u32 separate_alpha;
- Equation equation_rgb;
- Factor factor_source_rgb;
- Factor factor_dest_rgb;
- Equation equation_a;
- Factor factor_source_a;
- Factor factor_dest_a;
- INSERT_PADDING_WORDS_NOINIT(1);
- };
-
- enum class TessellationPrimitive : u32 {
- Isolines = 0,
- Triangles = 1,
- Quads = 2,
+ Equation color_op;
+ Factor color_source;
+ Factor color_dest;
+ Equation alpha_op;
+ Factor alpha_source;
+ u32 enable_global_color_key;
+ Factor alpha_dest;
+
+ u32 single_rop_control_enable;
+ u32 enable[NumRenderTargets];
};
- enum class TessellationSpacing : u32 {
- Equal = 0,
- FractionalOdd = 1,
- FractionalEven = 2,
+ struct BlendPerTarget {
+ u32 separate_alpha;
+ Blend::Equation color_op;
+ Blend::Factor color_source;
+ Blend::Factor color_dest;
+ Blend::Equation alpha_op;
+ Blend::Factor alpha_source;
+ Blend::Factor alpha_dest;
+ INSERT_PADDING_BYTES_NOINIT(0x4);
};
+ static_assert(sizeof(BlendPerTarget) == 0x20);
enum class PolygonMode : u32 {
- Point = 0x1b00,
- Line = 0x1b01,
- Fill = 0x1b02,
+ Point = 0x1B00,
+ Line = 0x1B01,
+ Fill = 0x1B02,
};
enum class ShadowRamControl : u32 {
@@ -589,18 +1101,22 @@ public:
NegativeW = 7,
};
- enum class SamplerIndex : u32 {
+ enum class SamplerBinding : u32 {
Independently = 0,
- ViaHeaderIndex = 1,
+ ViaHeaderBinding = 1,
};
struct TileMode {
+ enum class DimensionControl : u32 {
+ DepthDefinesArray = 0,
+ DepthDefinesDepth = 1,
+ };
union {
BitField<0, 4, u32> block_width;
BitField<4, 4, u32> block_height;
BitField<8, 4, u32> block_depth;
BitField<12, 1, u32> is_pitch_linear;
- BitField<16, 1, u32> is_3d;
+ BitField<16, 1, DimensionControl> dim_control;
};
};
static_assert(sizeof(TileMode) == 4);
@@ -616,23 +1132,25 @@ public:
BitField<0, 16, u32> depth;
BitField<16, 1, u32> volume;
};
- u32 layer_stride;
+ u32 array_pitch;
u32 base_layer;
- INSERT_PADDING_WORDS_NOINIT(7);
+ u32 mark_ieee_clean;
+ INSERT_PADDING_BYTES_NOINIT(0x18);
GPUVAddr Address() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
}
};
+ static_assert(sizeof(RenderTargetConfig) == 0x40);
struct ColorMask {
union {
u32 raw;
- BitField<0, 4, u32> R;
- BitField<4, 4, u32> G;
- BitField<8, 4, u32> B;
- BitField<12, 4, u32> A;
+ BitField<0, 1, u32> R;
+ BitField<4, 1, u32> G;
+ BitField<8, 1, u32> B;
+ BitField<12, 1, u32> A;
};
};
@@ -643,6 +1161,7 @@ public:
f32 translate_x;
f32 translate_y;
f32 translate_z;
+
union {
u32 raw;
BitField<0, 3, ViewportSwizzle> x;
@@ -650,7 +1169,11 @@ public:
BitField<8, 3, ViewportSwizzle> z;
BitField<12, 3, ViewportSwizzle> w;
} swizzle;
- INSERT_PADDING_WORDS_NOINIT(1);
+
+ union {
+ BitField<0, 5, u32> x;
+ BitField<8, 5, u32> y;
+ } snap_grid_precision;
Common::Rectangle<f32> GetRect() const {
return {
@@ -677,21 +1200,14 @@ public:
return translate_y + std::fabs(scale_y) - GetY();
}
};
+ static_assert(sizeof(ViewportTransform) == 0x20);
- struct ScissorTest {
- u32 enable;
- union {
- BitField<0, 16, u32> min_x;
- BitField<16, 16, u32> max_x;
+ struct Viewport {
+ enum class PixelCenter : u32 {
+ HalfIntegers = 0,
+ Integers = 1,
};
- union {
- BitField<0, 16, u32> min_y;
- BitField<16, 16, u32> max_y;
- };
- u32 fill;
- };
- struct ViewPort {
union {
BitField<0, 16, u32> x;
BitField<16, 16, u32> width;
@@ -703,726 +1219,1820 @@ public:
float depth_range_near;
float depth_range_far;
};
+ static_assert(sizeof(Viewport) == 0x10);
- struct TransformFeedbackBinding {
- u32 buffer_enable;
- u32 address_high;
- u32 address_low;
- s32 buffer_size;
- s32 buffer_offset;
- INSERT_PADDING_WORDS_NOINIT(3);
-
- GPUVAddr Address() const {
- return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
- address_low);
- }
+ struct Window {
+ union {
+ BitField<0, 16, u32> x_min;
+ BitField<16, 16, u32> x_max;
+ };
+ union {
+ BitField<0, 16, u32> y_min;
+ BitField<16, 16, u32> y_max;
+ };
};
- static_assert(sizeof(TransformFeedbackBinding) == 32);
+ static_assert(sizeof(Window) == 0x8);
- struct TransformFeedbackLayout {
- u32 stream;
- u32 varying_count;
- u32 stride;
- INSERT_PADDING_WORDS_NOINIT(1);
+ struct ClipIdExtent {
+ union {
+ BitField<0, 16, u32> x;
+ BitField<16, 16, u32> width;
+ };
+ union {
+ BitField<0, 16, u32> y;
+ BitField<16, 16, u32> height;
+ };
+ };
+ static_assert(sizeof(ClipIdExtent) == 0x8);
+
+ enum class VisibleCallLimit : u32 {
+ Limit0 = 0,
+ Limit1 = 1,
+ Limit2 = 2,
+ Limit4 = 3,
+ Limit8 = 4,
+ Limit16 = 5,
+ Limit32 = 6,
+ Limit64 = 7,
+ Limit128 = 8,
+ None = 15,
};
- static_assert(sizeof(TransformFeedbackLayout) == 16);
-
- bool IsShaderConfigEnabled(std::size_t index) const {
- // The VertexB is always enabled.
- if (index == static_cast<std::size_t>(Regs::ShaderProgram::VertexB)) {
- return true;
- }
- return shader_config[index].enable != 0;
- }
-
- bool IsShaderConfigEnabled(Regs::ShaderProgram type) const {
- return IsShaderConfigEnabled(static_cast<std::size_t>(type));
- }
-
- union {
- struct {
- INSERT_PADDING_WORDS_NOINIT(0x44);
- u32 wait_for_idle;
+ struct StatisticsCounter {
+ union {
+ BitField<0, 1, u32> da_vertices;
+ BitField<1, 1, u32> da_primitives;
+ BitField<2, 1, u32> vs_invocations;
+ BitField<3, 1, u32> gs_invocations;
+ BitField<4, 1, u32> gs_primitives;
+ BitField<5, 1, u32> streaming_primitives_succeeded;
+ BitField<6, 1, u32> streaming_primitives_needed;
+ BitField<7, 1, u32> clipper_invocations;
+ BitField<8, 1, u32> clipper_primitives;
+ BitField<9, 1, u32> ps_invocations;
+ BitField<11, 1, u32> ti_invocations;
+ BitField<12, 1, u32> ts_invocations;
+ BitField<13, 1, u32> ts_primitives;
+ BitField<14, 1, u32> total_streaming_primitives_needed_succeeded;
+ BitField<10, 1, u32> vtg_primitives_out;
+ BitField<15, 1, u32> alpha_beta_clocks;
+ };
+ };
- struct {
- u32 upload_address;
- u32 data;
- u32 entry;
- u32 bind;
- } macros;
+ struct ClearRect {
+ union {
+ BitField<0, 16, u32> x_min;
+ BitField<16, 16, u32> x_max;
+ };
+ union {
+ BitField<0, 16, u32> y_min;
+ BitField<16, 16, u32> y_max;
+ };
+ };
- ShadowRamControl shadow_ram_control;
+ struct VertexBuffer {
+ u32 first;
+ u32 count;
+ };
- INSERT_PADDING_WORDS_NOINIT(0x16);
+ struct InvalidateShaderCacheNoWFI {
+ union {
+ BitField<0, 1, u32> instruction;
+ BitField<4, 1, u32> global_data;
+ BitField<12, 1, u32> constant;
+ };
+ };
- Upload::Registers upload;
- struct {
- union {
- BitField<0, 1, u32> linear;
- };
- } exec_upload;
+ struct ZCullSerialization {
+ enum class Applied : u32 {
+ Always = 0,
+ LateZ = 1,
+ OutOfGamutZ = 2,
+ LateZOrOutOfGamutZ = 3,
+ };
+ union {
+ BitField<0, 1, u32> enable;
+ BitField<4, 2, Applied> applied;
+ };
+ };
- u32 data_upload;
+ struct ZCullDirFormat {
+ enum class Zdir : u32 {
+ Less = 0,
+ Greater = 1,
+ };
+ enum class Zformat : u32 {
+ MSB = 0,
+ FP = 1,
+ Ztrick = 2,
+ Zf32 = 3,
+ };
- INSERT_PADDING_WORDS_NOINIT(0x16);
+ union {
+ BitField<0, 16, Zdir> dir;
+ BitField<16, 16, Zformat> format;
+ };
+ };
- u32 force_early_fragment_tests;
+ struct IteratedBlend {
+ union {
+ BitField<0, 1, u32> enable;
+ BitField<1, 1, u32> enable_alpha;
+ };
+ u32 pass_count;
+ };
- INSERT_PADDING_WORDS_NOINIT(0x2D);
+ struct ZCullCriterion {
+ enum class Sfunc : u32 {
+ Never = 0,
+ Less = 1,
+ Equal = 2,
+ LessOrEqual = 3,
+ Greater = 4,
+ NotEqual = 5,
+ GreaterOrEqual = 6,
+ Always = 7,
+ };
- struct {
- union {
- BitField<0, 16, u32> sync_point;
- BitField<16, 1, u32> unknown;
- BitField<20, 1, u32> increment;
- };
- } sync_info;
+ union {
+ BitField<0, 8, Sfunc> sfunc;
+ BitField<8, 1, u32> no_invalidate;
+ BitField<9, 1, u32> force_match;
+ BitField<16, 8, u32> sref;
+ BitField<24, 8, u32> smask;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x15);
+ struct LoadIteratedBlend {
+ enum class Test : u32 {
+ False = 0,
+ True = 1,
+ Equal = 2,
+ NotEqual = 3,
+ LessThan = 4,
+ LessOrEqual = 5,
+ Greater = 6,
+ GreaterOrEqual = 7,
+ };
+ enum class Operation : u32 {
+ AddProducts = 0,
+ SubProducts = 1,
+ Min = 2,
+ Max = 3,
+ Reciprocal = 4,
+ Add = 5,
+ Sub = 6,
+ };
+ enum class OperandA : u32 {
+ SrcRGB = 0,
+ DstRGB = 1,
+ SrcAAA = 2,
+ DstAAA = 3,
+ Temp0_RGB = 4,
+ Temp1_RGB = 5,
+ Temp2_RGB = 6,
+ PBR_RGB = 7,
+ };
+ enum class OperandB : u32 {
+ Zero = 0,
+ One = 1,
+ SrcRGB = 2,
+ SrcAAA = 3,
+ OneMinusSrcAAA = 4,
+ DstRGB = 5,
+ DstAAA = 6,
+ OneMinusDstAAA = 7,
+ Temp0_RGB = 9,
+ Temp1_RGB = 10,
+ Temp2_RGB = 11,
+ PBR_RGB = 12,
+ ConstRGB = 13,
+ ZeroATimesB = 14,
+ };
+ enum class Swizzle : u32 {
+ RGB = 0,
+ GBR = 1,
+ RRR = 2,
+ GGG = 3,
+ BBB = 4,
+ RToA = 5,
+ };
+ enum class WriteMask : u32 {
+ RGB = 0,
+ ROnly = 1,
+ GOnly = 2,
+ BOnly = 3,
+ };
+ enum class Pass : u32 {
+ Temp0 = 0,
+ Temp1 = 1,
+ Temp2 = 2,
+ None = 3,
+ };
- union {
- BitField<0, 2, TessellationPrimitive> prim;
- BitField<4, 2, TessellationSpacing> spacing;
- BitField<8, 1, u32> cw;
- BitField<9, 1, u32> connected;
- } tess_mode;
+ u32 instruction_ptr;
+ union {
+ BitField<0, 3, Test> test;
+ BitField<3, 3, Operation> operation;
+ BitField<6, 3, u32> const_input;
+ BitField<9, 3, OperandA> operand_a;
+ BitField<12, 4, OperandB> operand_b;
+ BitField<16, 3, OperandA> operand_c;
+ BitField<19, 4, OperandB> operand_d;
+ BitField<23, 3, Swizzle> output_swizzle;
+ BitField<26, 2, WriteMask> output_mask;
+ BitField<28, 2, Pass> output_pass;
+ BitField<31, 1, u32> test_enabled;
+ };
+ };
- std::array<f32, 4> tess_level_outer;
- std::array<f32, 2> tess_level_inner;
+ struct ScissorTest {
+ u32 enable;
+ union {
+ BitField<0, 16, u32> min_x;
+ BitField<16, 16, u32> max_x;
+ };
+ union {
+ BitField<0, 16, u32> min_y;
+ BitField<16, 16, u32> max_y;
+ };
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ };
+ static_assert(sizeof(ScissorTest) == 0x10);
- INSERT_PADDING_WORDS_NOINIT(0x10);
+ struct VPCPerf {
+ union {
+ BitField<0, 8, u32> culled_small_lines;
+ BitField<8, 8, u32> culled_small_triangles;
+ BitField<16, 8, u32> nonculled_lines_and_points;
+ BitField<24, 8, u32> nonculled_triangles;
+ };
+ };
- u32 rasterize_enable;
+ struct ConstantColorRendering {
+ u32 enabled;
+ u32 red;
+ u32 green;
+ u32 blue;
+ u32 alpha;
+ };
- std::array<TransformFeedbackBinding, NumTransformFeedbackBuffers> tfb_bindings;
+ struct VertexStreamSubstitute {
+ u32 address_high;
+ u32 address_low;
- INSERT_PADDING_WORDS_NOINIT(0xC0);
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
+ };
- std::array<TransformFeedbackLayout, NumTransformFeedbackBuffers> tfb_layouts;
+ struct VTGWarpWatermarks {
+ union {
+ BitField<0, 16, u32> low;
+ BitField<16, 16, u32> high;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x1);
+ struct SampleMask {
+ struct Target {
+ union {
+ BitField<0, 1, u32> raster_out;
+ BitField<4, 1, u32> color_target;
+ };
+ u32 target;
+ };
+ struct Pos {
+ u32 x0_y0;
+ u32 x1_y0;
+ u32 x0_y1;
+ u32 x1_y1;
+ };
+ };
- u32 tfb_enabled;
+ enum class NonMultisampledZ : u32 {
+ PerSample = 0,
+ PixelCenter = 1,
+ };
- INSERT_PADDING_WORDS_NOINIT(0x2E);
+ enum class TIRMode : u32 {
+ Disabled = 0,
+ RasterNTargetM = 1,
+ };
- std::array<RenderTargetConfig, NumRenderTargets> rt;
+ enum class AntiAliasRaster : u32 {
+ Mode1x1 = 0,
+ Mode2x2 = 2,
+ Mode4x2_D3D = 4,
+ Mode2x1_D3D = 5,
+ Mode4x4 = 6,
+ };
- std::array<ViewportTransform, NumViewports> viewport_transform;
+ struct SurfaceClipIDMemory {
+ u32 address_high;
+ u32 address_low;
- std::array<ViewPort, NumViewports> viewports;
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
+ };
- INSERT_PADDING_WORDS_NOINIT(0x1D);
+ struct TIRModulation {
+ enum class Component : u32 {
+ None = 0,
+ RGB = 1,
+ AlphaOnly = 2,
+ RGBA = 3,
+ };
+ enum class Function : u32 {
+ Linear = 0,
+ Table = 1,
+ };
+ Component component;
+ Function function;
+ };
- struct {
- u32 first;
- u32 count;
- } vertex_buffer;
+ struct Zeta {
+ u32 address_high;
+ u32 address_low;
+ Tegra::DepthFormat format;
+ TileMode tile_mode;
+ u32 array_pitch;
- DepthMode depth_mode;
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
+ };
- float clear_color[4];
- float clear_depth;
+ struct SurfaceClip {
+ union {
+ BitField<0, 16, u32> x;
+ BitField<16, 16, u32> width;
+ };
+ union {
+ BitField<0, 16, u32> y;
+ BitField<16, 16, u32> height;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x3);
+ enum class L2CacheControlPolicy : u32 {
+ First = 0,
+ Normal = 1,
+ Last = 2,
+ };
- s32 clear_stencil;
+ struct L2CacheVAFRequests {
+ union {
+ BitField<0, 1, u32> system_memory_volatile;
+ BitField<4, 2, L2CacheControlPolicy> policy;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x2);
+ enum class ViewportMulticast : u32 {
+ ViewportOrder = 0,
+ PrimitiveOrder = 1,
+ };
- PolygonMode polygon_mode_front;
- PolygonMode polygon_mode_back;
+ struct TIRModulationCoeff {
+ union {
+ BitField<0, 8, u32> table_v0;
+ BitField<8, 8, u32> table_v1;
+ BitField<16, 8, u32> table_v2;
+ BitField<24, 8, u32> table_v3;
+ };
+ };
+ static_assert(sizeof(TIRModulationCoeff) == 0x4);
- INSERT_PADDING_WORDS_NOINIT(0x3);
+ struct ReduceColorThreshold {
+ union {
+ BitField<0, 8, u32> all_hit_once;
+ BitField<16, 8, u32> all_covered;
+ };
+ };
- u32 polygon_offset_point_enable;
- u32 polygon_offset_line_enable;
- u32 polygon_offset_fill_enable;
+ struct ClearControl {
+ union {
+ BitField<0, 1, u32> respect_stencil_mask;
+ BitField<4, 1, u32> use_clear_rect;
+ BitField<8, 1, u32> use_scissor;
+ BitField<12, 1, u32> use_viewport_clip0;
+ };
+ };
- u32 patch_vertices;
+ struct L2CacheRopNonInterlockedReads {
+ union {
+ BitField<4, 2, L2CacheControlPolicy> policy;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x4);
+ struct VertexOutputAttributeSkipMasks {
+ struct Attributes {
+ union {
+ BitField<0, 1, u32> attribute0_comp0;
+ BitField<1, 1, u32> attribute0_comp1;
+ BitField<2, 1, u32> attribute0_comp2;
+ BitField<3, 1, u32> attribute0_comp3;
+ BitField<4, 1, u32> attribute1_comp0;
+ BitField<5, 1, u32> attribute1_comp1;
+ BitField<6, 1, u32> attribute1_comp2;
+ BitField<7, 1, u32> attribute1_comp3;
+ BitField<8, 1, u32> attribute2_comp0;
+ BitField<9, 1, u32> attribute2_comp1;
+ BitField<10, 1, u32> attribute2_comp2;
+ BitField<11, 1, u32> attribute2_comp3;
+ BitField<12, 1, u32> attribute3_comp0;
+ BitField<13, 1, u32> attribute3_comp1;
+ BitField<14, 1, u32> attribute3_comp2;
+ BitField<15, 1, u32> attribute3_comp3;
+ BitField<16, 1, u32> attribute4_comp0;
+ BitField<17, 1, u32> attribute4_comp1;
+ BitField<18, 1, u32> attribute4_comp2;
+ BitField<19, 1, u32> attribute4_comp3;
+ BitField<20, 1, u32> attribute5_comp0;
+ BitField<21, 1, u32> attribute5_comp1;
+ BitField<22, 1, u32> attribute5_comp2;
+ BitField<23, 1, u32> attribute5_comp3;
+ BitField<24, 1, u32> attribute6_comp0;
+ BitField<25, 1, u32> attribute6_comp1;
+ BitField<26, 1, u32> attribute6_comp2;
+ BitField<27, 1, u32> attribute6_comp3;
+ BitField<28, 1, u32> attribute7_comp0;
+ BitField<29, 1, u32> attribute7_comp1;
+ BitField<30, 1, u32> attribute7_comp2;
+ BitField<31, 1, u32> attribute7_comp3;
+ };
+ };
- u32 fragment_barrier;
+ std::array<Attributes, 2> a;
+ std::array<Attributes, 2> b;
+ };
- INSERT_PADDING_WORDS_NOINIT(0x7);
+ struct TIRControl {
+ union {
+ BitField<0, 1, u32> z_pass_pixel_count_use_raster_samples;
+ BitField<4, 1, u32> alpha_coverage_use_raster_samples;
+ BitField<1, 1, u32> reduce_coverage;
+ };
+ };
- std::array<ScissorTest, NumViewports> scissor_test;
+ enum class FillViaTriangleMode : u32 {
+ Disabled = 0,
+ FillAll = 1,
+ FillBoundingBox = 2,
+ };
- INSERT_PADDING_WORDS_NOINIT(0x15);
+ struct PsTicketDispenserValue {
+ union {
+ BitField<0, 8, u32> index;
+ BitField<8, 16, u32> value;
+ };
+ };
- s32 stencil_back_func_ref;
- u32 stencil_back_mask;
- u32 stencil_back_func_mask;
+ struct RegisterWatermarks {
+ union {
+ BitField<0, 16, u32> low;
+ BitField<16, 16, u32> high;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x5);
+ enum class InvalidateCacheLines : u32 {
+ All = 0,
+ One = 1,
+ };
- u32 invalidate_texture_data_cache;
+ struct InvalidateTextureDataCacheNoWfi {
+ union {
+ BitField<0, 1, InvalidateCacheLines> lines;
+ BitField<4, 22, u32> tag;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x1);
+ struct ZCullRegionEnable {
+ union {
+ BitField<0, 1, u32> enable_z;
+ BitField<4, 1, u32> enable_stencil;
+ BitField<1, 1, u32> rect_clear;
+ BitField<2, 1, u32> use_rt_array_index;
+ BitField<5, 16, u32> rt_array_index;
+ BitField<3, 1, u32> make_conservative;
+ };
+ };
- u32 tiled_cache_barrier;
+ enum class FillMode : u32 {
+ Point = 1,
+ Wireframe = 2,
+ Solid = 3,
+ };
- INSERT_PADDING_WORDS_NOINIT(0x4);
+ enum class ShadeMode : u32 {
+ Flat = 0x1,
+ Gouraud = 0x2,
+ GL_Flat = 0x1D00,
+ GL_Smooth = 0x1D01,
+ };
- u32 color_mask_common;
+ enum class AlphaToCoverageDither : u32 {
+ Footprint_1x1 = 0,
+ Footprint_2x2 = 1,
+ Footprint_1x1_Virtual = 2,
+ };
- INSERT_PADDING_WORDS_NOINIT(0x2);
+ struct InlineIndex4x8Align {
+ union {
+ BitField<0, 30, u32> count;
+ BitField<30, 2, u32> start;
+ };
+ };
- f32 depth_bounds[2];
+ struct InlineIndex4x8Index {
+ union {
+ BitField<0, 8, u32> index0;
+ BitField<8, 8, u32> index1;
+ BitField<16, 8, u32> index2;
+ BitField<24, 8, u32> index3;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x2);
+ enum class D3DCullMode : u32 {
+ None = 0,
+ CW = 1,
+ CCW = 2,
+ };
- u32 rt_separate_frag_data;
+ struct BlendColor {
+ f32 r;
+ f32 g;
+ f32 b;
+ f32 a;
+ };
- INSERT_PADDING_WORDS_NOINIT(0x1);
+ struct StencilOp {
+ enum class Op : u32 {
+ Keep_D3D = 1,
+ Zero_D3D = 2,
+ Replace_D3D = 3,
+ IncrSaturate_D3D = 4,
+ DecrSaturate_D3D = 5,
+ Invert_D3D = 6,
+ Incr_D3D = 7,
+ Decr_D3D = 8,
+
+ Keep_GL = 0x1E00,
+ Zero_GL = 0,
+ Replace_GL = 0x1E01,
+ IncrSaturate_GL = 0x1E02,
+ DecrSaturate_GL = 0x1E03,
+ Invert_GL = 0x150A,
+ Incr_GL = 0x8507,
+ Decr_GL = 0x8508,
+ };
- u32 multisample_raster_enable;
- u32 multisample_raster_samples;
- std::array<u32, 4> multisample_sample_mask;
+ Op fail;
+ Op zfail;
+ Op zpass;
+ ComparisonOp func;
+ };
- INSERT_PADDING_WORDS_NOINIT(0x5);
+ struct PsSaturate {
+ // Opposite of DepthMode
+ enum class Depth : u32 {
+ ZeroToOne = 0,
+ MinusOneToOne = 1,
+ };
- struct {
- u32 address_high;
- u32 address_low;
- Tegra::DepthFormat format;
- TileMode tile_mode;
- u32 layer_stride;
+ union {
+ BitField<0, 1, u32> output0_enable;
+ BitField<1, 1, Depth> output0_range;
+ BitField<4, 1, u32> output1_enable;
+ BitField<5, 1, Depth> output1_range;
+ BitField<8, 1, u32> output2_enable;
+ BitField<9, 1, Depth> output2_range;
+ BitField<12, 1, u32> output3_enable;
+ BitField<13, 1, Depth> output3_range;
+ BitField<16, 1, u32> output4_enable;
+ BitField<17, 1, Depth> output4_range;
+ BitField<20, 1, u32> output5_enable;
+ BitField<21, 1, Depth> output5_range;
+ BitField<24, 1, u32> output6_enable;
+ BitField<25, 1, Depth> output6_range;
+ BitField<28, 1, u32> output7_enable;
+ BitField<29, 1, Depth> output7_range;
+ };
- GPUVAddr Address() const {
- return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
- address_low);
- }
- } zeta;
+ bool AnyEnabled() const {
+ return output0_enable || output1_enable || output2_enable || output3_enable ||
+ output4_enable || output5_enable || output6_enable || output7_enable;
+ }
+ };
- struct {
- union {
- BitField<0, 16, u32> x;
- BitField<16, 16, u32> width;
- };
- union {
- BitField<0, 16, u32> y;
- BitField<16, 16, u32> height;
- };
- } render_area;
+ struct WindowOrigin {
+ enum class Mode : u32 {
+ UpperLeft = 0,
+ LowerLeft = 1,
+ };
+ union {
+ BitField<0, 1, Mode> mode;
+ BitField<4, 1, u32> flip_y;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x3F);
+ struct IteratedBlendConstants {
+ u32 r;
+ u32 g;
+ u32 b;
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ };
+ static_assert(sizeof(IteratedBlendConstants) == 0x10);
+ struct UserClip {
+ struct Enable {
union {
- BitField<0, 4, u32> stencil;
- BitField<4, 4, u32> unknown;
- BitField<8, 4, u32> scissor;
- BitField<12, 4, u32> viewport;
- } clear_flags;
-
- INSERT_PADDING_WORDS_NOINIT(0x10);
-
- u32 fill_rectangle;
-
- INSERT_PADDING_WORDS_NOINIT(0x2);
-
- u32 conservative_raster_enable;
-
- INSERT_PADDING_WORDS_NOINIT(0x5);
-
- std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format;
+ u32 raw;
+ BitField<0, 1, u32> plane0;
+ BitField<1, 1, u32> plane1;
+ BitField<2, 1, u32> plane2;
+ BitField<3, 1, u32> plane3;
+ BitField<4, 1, u32> plane4;
+ BitField<5, 1, u32> plane5;
+ BitField<6, 1, u32> plane6;
+ BitField<7, 1, u32> plane7;
+ };
- std::array<MsaaSampleLocation, 4> multisample_sample_locations;
+ bool AnyEnabled() const {
+ return plane0 || plane1 || plane2 || plane3 || plane4 || plane5 || plane6 ||
+ plane7;
+ }
+ };
- INSERT_PADDING_WORDS_NOINIT(0x2);
+ struct Op {
+ enum class ClipOrCull : u32 {
+ Clip = 0,
+ Cull = 1,
+ };
union {
- BitField<0, 1, u32> enable;
- BitField<4, 3, u32> target;
- } multisample_coverage_to_color;
-
- INSERT_PADDING_WORDS_NOINIT(0x8);
-
- struct {
- union {
- BitField<0, 4, u32> count;
- BitField<4, 3, u32> map_0;
- BitField<7, 3, u32> map_1;
- BitField<10, 3, u32> map_2;
- BitField<13, 3, u32> map_3;
- BitField<16, 3, u32> map_4;
- BitField<19, 3, u32> map_5;
- BitField<22, 3, u32> map_6;
- BitField<25, 3, u32> map_7;
- };
-
- u32 Map(std::size_t index) const {
- const std::array<u32, NumRenderTargets> maps{map_0, map_1, map_2, map_3,
- map_4, map_5, map_6, map_7};
- ASSERT(index < maps.size());
- return maps[index];
- }
- } rt_control;
-
- INSERT_PADDING_WORDS_NOINIT(0x2);
-
- u32 zeta_width;
- u32 zeta_height;
- union {
- BitField<0, 16, u32> zeta_depth;
- BitField<16, 1, u32> zeta_volume;
+ u32 raw;
+ BitField<0, 1, ClipOrCull> plane0;
+ BitField<4, 1, ClipOrCull> plane1;
+ BitField<8, 1, ClipOrCull> plane2;
+ BitField<12, 1, ClipOrCull> plane3;
+ BitField<16, 1, ClipOrCull> plane4;
+ BitField<20, 1, ClipOrCull> plane5;
+ BitField<24, 1, ClipOrCull> plane6;
+ BitField<28, 1, ClipOrCull> plane7;
};
+ };
+ };
- SamplerIndex sampler_index;
+ struct AntiAliasAlphaControl {
+ union {
+ BitField<0, 1, u32> alpha_to_coverage;
+ BitField<4, 1, u32> alpha_to_one;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x2);
+ struct RenderEnable {
+ enum class Override : u32 {
+ UseRenderEnable = 0,
+ AlwaysRender = 1,
+ NeverRender = 2,
+ };
- std::array<u32, 8> gp_passthrough_mask;
+ enum class Mode : u32 {
+ False = 0,
+ True = 1,
+ Conditional = 2,
+ IfEqual = 3,
+ IfNotEqual = 4,
+ };
- INSERT_PADDING_WORDS_NOINIT(0x1B);
+ u32 address_high;
+ u32 address_low;
+ Mode mode;
- u32 depth_test_enable;
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
+ };
- INSERT_PADDING_WORDS_NOINIT(0x5);
+ struct TexSampler {
+ u32 address_high;
+ u32 address_low;
+ u32 limit;
- u32 independent_blend_enable;
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
+ };
- u32 depth_write_enabled;
+ struct TexHeader {
+ u32 address_high;
+ u32 address_low;
+ u32 limit;
- u32 alpha_test_enabled;
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
+ };
- INSERT_PADDING_WORDS_NOINIT(0x6);
+ enum class ZCullRegionFormat : u32 {
+ Z_4x4 = 0,
+ ZS_4x4 = 1,
+ Z_4x2 = 2,
+ Z_2x4 = 3,
+ Z_16x8_4x4 = 4,
+ Z_8x8_4x2 = 5,
+ Z_8x8_2x4 = 6,
+ Z_16x16_4x8 = 7,
+ Z_4x8_2x2 = 8,
+ ZS_16x8_4x2 = 9,
+ ZS_16x8_2x4 = 10,
+ ZS_8x8_2x2 = 11,
+ Z_4x8_1x1 = 12,
+ };
- u32 d3d_cull_mode;
+ struct RtLayer {
+ enum class Control {
+ LayerSelectsLayer = 0,
+ GeometryShaderSelectsLayer = 1,
+ };
- ComparisonOp depth_test_func;
- float alpha_test_ref;
- ComparisonOp alpha_test_func;
- u32 draw_tfb_stride;
- struct {
- float r;
- float g;
- float b;
- float a;
- } blend_color;
+ union {
+ BitField<0, 16, u32> layer;
+ BitField<16, 1, u32> control;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x4);
+ struct InlineIndex2x16 {
+ union {
+ BitField<0, 31, u32> count;
+ BitField<31, 1, u32> start_odd;
+ };
+ union {
+ BitField<0, 16, u32> even;
+ BitField<16, 16, u32> odd;
+ };
+ };
- struct {
- u32 separate_alpha;
- Blend::Equation equation_rgb;
- Blend::Factor factor_source_rgb;
- Blend::Factor factor_dest_rgb;
- Blend::Equation equation_a;
- Blend::Factor factor_source_a;
- INSERT_PADDING_WORDS_NOINIT(1);
- Blend::Factor factor_dest_a;
+ struct VertexGlobalBaseOffset {
+ u32 address_high;
+ u32 address_low;
- u32 enable_common;
- u32 enable[NumRenderTargets];
- } blend;
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
+ };
- u32 stencil_enable;
- StencilOp stencil_front_op_fail;
- StencilOp stencil_front_op_zfail;
- StencilOp stencil_front_op_zpass;
- ComparisonOp stencil_front_func_func;
- s32 stencil_front_func_ref;
- u32 stencil_front_func_mask;
- u32 stencil_front_mask;
+ struct ZCullRegionPixelOffset {
+ u32 width;
+ u32 height;
+ };
- INSERT_PADDING_WORDS_NOINIT(0x2);
+ struct PointSprite {
+ enum class RMode : u32 {
+ Zero = 0,
+ FromR = 1,
+ FromS = 2,
+ };
+ enum class Origin : u32 {
+ Bottom = 0,
+ Top = 1,
+ };
+ enum class Texture : u32 {
+ Passthrough = 0,
+ Generate = 1,
+ };
+
+ union {
+ BitField<0, 2, RMode> rmode;
+ BitField<2, 1, Origin> origin;
+ BitField<3, 1, Texture> texture0;
+ BitField<4, 1, Texture> texture1;
+ BitField<5, 1, Texture> texture2;
+ BitField<6, 1, Texture> texture3;
+ BitField<7, 1, Texture> texture4;
+ BitField<8, 1, Texture> texture5;
+ BitField<9, 1, Texture> texture6;
+ BitField<10, 1, Texture> texture7;
+ BitField<11, 1, Texture> texture8;
+ BitField<12, 1, Texture> texture9;
+ };
+ };
- u32 frag_color_clamp;
+ struct ProgramRegion {
+ u32 address_high;
+ u32 address_low;
- union {
- BitField<0, 1, u32> y_negate;
- BitField<4, 1, u32> triangle_rast_flip;
- } screen_y_control;
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
+ };
- float line_width_smooth;
- float line_width_aliased;
+ struct DefaultAttributes {
+ enum class Diffuse : u32 {
+ Vector_0001 = 0,
+ Vector_1111 = 1,
+ };
+ enum class Specular : u32 {
+ Vector_0000 = 0,
+ Vector_0001 = 1,
+ };
+ enum class Vector : u32 {
+ Vector_0000 = 0,
+ Vector_0001 = 1,
+ };
+ enum class FixedFncTexture : u32 {
+ Vector_0000 = 0,
+ Vector_0001 = 1,
+ };
+ enum class DX9Color0 : u32 {
+ Vector_0000 = 0,
+ Vector_1111 = 1,
+ };
+ enum class DX9Color1To15 : u32 {
+ Vector_0000 = 0,
+ Vector_0001 = 1,
+ };
- INSERT_PADDING_WORDS_NOINIT(0x1B);
+ union {
+ BitField<0, 1, Diffuse> color_front_diffuse;
+ BitField<1, 1, Specular> color_front_specular;
+ BitField<2, 1, Vector> generic_vector;
+ BitField<3, 1, FixedFncTexture> fixed_fnc_texture;
+ BitField<4, 1, DX9Color0> dx9_color0;
+ BitField<5, 1, DX9Color1To15> dx9_color1_to_15;
+ };
+ };
- u32 invalidate_sampler_cache_no_wfi;
- u32 invalidate_texture_header_cache_no_wfi;
+ struct Draw {
+ enum class PrimitiveId : u32 {
+ First = 0,
+ Unchanged = 1,
+ };
+ enum class InstanceId : u32 {
+ First = 0,
+ Subsequent = 1,
+ Unchanged = 2,
+ };
+ enum class SplitMode : u32 {
+ NormalBeginNormal = 0,
+ NormalBeginOpen = 1,
+ OpenBeginOpen = 2,
+ OpenBeginNormal = 3,
+ };
- INSERT_PADDING_WORDS_NOINIT(0x2);
+ u32 end;
+ union {
+ u32 begin;
+ BitField<0, 16, PrimitiveTopology> topology;
+ BitField<24, 1, PrimitiveId> primitive_id;
+ BitField<26, 2, InstanceId> instance_id;
+ BitField<29, 2, SplitMode> split_mode;
+ };
+ };
- u32 vb_element_base;
- u32 vb_base_instance;
+ struct VertexIdCopy {
+ union {
+ BitField<0, 1, u32> enable;
+ BitField<4, 8, u32> attribute_slot;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x35);
+ struct ShaderBasedCull {
+ union {
+ BitField<1, 1, u32> batch_cull_enable;
+ BitField<0, 1, u32> before_fetch_enable;
+ };
+ };
- u32 clip_distance_enabled;
+ struct ClassVersion {
+ union {
+ BitField<0, 16, u32> current;
+ BitField<16, 16, u32> oldest_supported;
+ };
+ };
- u32 samplecnt_enable;
+ struct PrimitiveRestart {
+ u32 enabled;
+ u32 index;
+ };
- float point_size;
+ struct OutputVertexId {
+ union {
+ BitField<12, 1, u32> uses_array_start;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x1);
+ enum class PointCenterMode : u32 {
+ GL = 0,
+ D3D = 1,
+ };
- u32 point_sprite_enable;
+ enum class LineSmoothParams : u32 {
+ Falloff_1_00 = 0,
+ Falloff_1_33 = 1,
+ Falloff_1_66 = 2,
+ };
- INSERT_PADDING_WORDS_NOINIT(0x3);
+ struct LineSmoothEdgeTable {
+ union {
+ BitField<0, 8, u32> v0;
+ BitField<8, 8, u32> v1;
+ BitField<16, 8, u32> v2;
+ BitField<24, 8, u32> v3;
+ };
+ };
- CounterReset counter_reset;
+ struct LineStippleParams {
+ union {
+ BitField<0, 8, u32> factor;
+ BitField<8, 16, u32> pattern;
+ };
+ };
- u32 multisample_enable;
+ enum class ProvokingVertex : u32 {
+ First = 0,
+ Last = 1,
+ };
- u32 zeta_enable;
+ struct ShaderControl {
+ enum class Partial : u32 {
+ Zero = 0,
+ Infinity = 1,
+ };
+ enum class FP32NanBehavior : u32 {
+ Legacy = 0,
+ FP64Compatible = 1,
+ };
+ enum class FP32F2INanBehavior : u32 {
+ PassZero = 0,
+ PassIndefinite = 1,
+ };
- union {
- BitField<0, 1, u32> alpha_to_coverage;
- BitField<4, 1, u32> alpha_to_one;
- } multisample_control;
+ union {
+ BitField<0, 1, Partial> default_partial;
+ BitField<1, 1, FP32NanBehavior> fp32_nan_behavior;
+ BitField<2, 1, FP32F2INanBehavior> fp32_f2i_nan_behavior;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x4);
+ struct SphVersion {
+ union {
+ BitField<0, 16, u32> current;
+ BitField<16, 16, u32> oldest_supported;
+ };
+ };
- struct {
- u32 address_high;
- u32 address_low;
- ConditionMode mode;
+ struct AlphaToCoverageOverride {
+ union {
+ BitField<0, 1, u32> qualify_by_anti_alias_enable;
+ BitField<1, 1, u32> qualify_by_ps_sample_mask_enable;
+ };
+ };
- GPUVAddr Address() const {
- return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
- address_low);
- }
- } condition;
+ struct AamVersion {
+ union {
+ BitField<0, 16, u32> current;
+ BitField<16, 16, u32> oldest_supported;
+ };
+ };
- struct {
- u32 address_high;
- u32 address_low;
- u32 limit;
+ struct IndexBuffer {
+ u32 start_addr_high;
+ u32 start_addr_low;
+ u32 limit_addr_high;
+ u32 limit_addr_low;
+ IndexFormat format;
+ u32 first;
+ u32 count;
+
+ unsigned FormatSizeInBytes() const {
+ switch (format) {
+ case IndexFormat::UnsignedByte:
+ return 1;
+ case IndexFormat::UnsignedShort:
+ return 2;
+ case IndexFormat::UnsignedInt:
+ return 4;
+ }
+ ASSERT(false);
+ return 1;
+ }
- GPUVAddr Address() const {
- return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
- address_low);
- }
- } tsc;
+ GPUVAddr StartAddress() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(start_addr_high) << 32) |
+ start_addr_low);
+ }
- INSERT_PADDING_WORDS_NOINIT(0x1);
+ GPUVAddr EndAddress() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(limit_addr_high) << 32) |
+ limit_addr_low);
+ }
- float polygon_offset_factor;
+ /// Adjust the index buffer offset so it points to the first desired index.
+ GPUVAddr IndexStart() const {
+ return StartAddress() +
+ static_cast<size_t>(first) * static_cast<size_t>(FormatSizeInBytes());
+ }
+ };
- u32 line_smooth_enable;
+ struct IndexBufferSmall {
+ union {
+ BitField<0, 16, u32> first;
+ BitField<16, 12, u32> count;
+ BitField<28, 4, PrimitiveTopology> topology;
+ };
+ };
- struct {
- u32 address_high;
- u32 address_low;
- u32 limit;
+ struct VertexStreamInstances {
+ std::array<u32, NumVertexArrays> is_instanced;
- GPUVAddr Address() const {
- return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
- address_low);
- }
- } tic;
+ /// Returns whether the vertex array specified by index is supposed to be
+ /// accessed per instance or not.
+ bool IsInstancingEnabled(std::size_t index) const {
+ return is_instanced[index];
+ }
+ };
- INSERT_PADDING_WORDS_NOINIT(0x5);
+ struct AttributePointSize {
+ union {
+ BitField<0, 1, u32> enabled;
+ BitField<4, 8, u32> slot;
+ };
+ };
- u32 stencil_two_side_enable;
- StencilOp stencil_back_op_fail;
- StencilOp stencil_back_op_zfail;
- StencilOp stencil_back_op_zpass;
- ComparisonOp stencil_back_func_func;
+ struct ViewportClipControl {
+ enum class GeometryGuardband : u32 {
+ Scale256 = 0,
+ Scale1 = 1,
+ };
+ enum class GeometryClip : u32 {
+ WZero = 0,
+ Passthrough = 1,
+ FrustumXY = 2,
+ FrustumXYZ = 3,
+ WZeroNoZCull = 4,
+ FrustumZ = 5,
+ WZeroTriFillOrClip = 6,
+ };
+ enum class GeometryGuardbandZ : u32 {
+ SameAsXY = 0,
+ Scale256 = 1,
+ Scale1 = 2,
+ };
- INSERT_PADDING_WORDS_NOINIT(0x4);
+ union {
+ BitField<0, 1, u32> depth_0_to_1;
+ BitField<3, 1, u32> pixel_min_z;
+ BitField<4, 1, u32> pixel_max_z;
+ BitField<7, 1, GeometryGuardband> geometry_guardband;
+ BitField<11, 3, GeometryClip> geometry_clip;
+ BitField<1, 2, GeometryGuardbandZ> geometry_guardband_z;
+ };
+ };
- u32 framebuffer_srgb;
+ enum class PrimitiveTopologyControl : u32 {
+ UseInBeginMethods = 0,
+ UseSeparateState = 1,
+ };
- float polygon_offset_units;
+ struct WindowClip {
+ enum class Type : u32 {
+ Inclusive = 0,
+ Exclusive = 1,
+ ClipAll = 2,
+ };
- INSERT_PADDING_WORDS_NOINIT(0x4);
+ u32 enable;
+ Type type;
+ };
- Tegra::Texture::MsaaMode multisample_mode;
+ enum class InvalidateZCull : u32 {
+ Invalidate = 0,
+ };
- INSERT_PADDING_WORDS_NOINIT(0xC);
+ struct ZCull {
+ union {
+ BitField<0, 1, u32> z_enable;
+ BitField<1, 1, u32> stencil_enable;
+ };
+ union {
+ BitField<0, 1, u32> z_min_enbounded;
+ BitField<1, 1, u32> z_max_unbounded;
+ };
+ };
- union {
- BitField<2, 1, u32> coord_origin;
- BitField<3, 10, u32> enable;
- } point_coord_replace;
-
- struct {
- u32 code_address_high;
- u32 code_address_low;
-
- GPUVAddr CodeAddress() const {
- return static_cast<GPUVAddr>(
- (static_cast<GPUVAddr>(code_address_high) << 32) | code_address_low);
- }
- } code_address;
- INSERT_PADDING_WORDS_NOINIT(1);
-
- struct {
- u32 vertex_end_gl;
- union {
- u32 vertex_begin_gl;
- BitField<0, 16, PrimitiveTopology> topology;
- BitField<26, 1, u32> instance_next;
- BitField<27, 1, u32> instance_cont;
- };
- } draw;
-
- INSERT_PADDING_WORDS_NOINIT(0xA);
-
- struct {
- u32 enabled;
- u32 index;
- } primitive_restart;
-
- INSERT_PADDING_WORDS_NOINIT(0xE);
-
- u32 provoking_vertex_last;
-
- INSERT_PADDING_WORDS_NOINIT(0x50);
-
- struct {
- u32 start_addr_high;
- u32 start_addr_low;
- u32 end_addr_high;
- u32 end_addr_low;
- IndexFormat format;
- u32 first;
- u32 count;
-
- unsigned FormatSizeInBytes() const {
- switch (format) {
- case IndexFormat::UnsignedByte:
- return 1;
- case IndexFormat::UnsignedShort:
- return 2;
- case IndexFormat::UnsignedInt:
- return 4;
- }
- ASSERT(false);
- return 1;
- }
-
- GPUVAddr StartAddress() const {
- return static_cast<GPUVAddr>(
- (static_cast<GPUVAddr>(start_addr_high) << 32) | start_addr_low);
- }
-
- GPUVAddr EndAddress() const {
- return static_cast<GPUVAddr>((static_cast<GPUVAddr>(end_addr_high) << 32) |
- end_addr_low);
- }
-
- /// Adjust the index buffer offset so it points to the first desired index.
- GPUVAddr IndexStart() const {
- return StartAddress() + static_cast<size_t>(first) *
- static_cast<size_t>(FormatSizeInBytes());
- }
- } index_array;
+ struct LogicOp {
+ enum class Op : u32 {
+ Clear = 0x1500,
+ And = 0x1501,
+ AndReverse = 0x1502,
+ Copy = 0x1503,
+ AndInverted = 0x1504,
+ NoOp = 0x1505,
+ Xor = 0x1506,
+ Or = 0x1507,
+ Nor = 0x1508,
+ Equiv = 0x1509,
+ Invert = 0x150A,
+ OrReverse = 0x150B,
+ CopyInverted = 0x150C,
+ OrInverted = 0x150D,
+ Nand = 0x150E,
+ Set = 0x150F,
+ };
- union {
- BitField<0, 16, u32> first;
- BitField<16, 16, u32> count;
- } small_index;
+ u32 enable;
+ Op op;
+ };
- union {
- BitField<0, 16, u32> first;
- BitField<16, 16, u32> count;
- } small_index_2;
+ struct ClearSurface {
+ union {
+ u32 raw;
+ BitField<0, 1, u32> Z;
+ BitField<1, 1, u32> S;
+ BitField<2, 1, u32> R;
+ BitField<3, 1, u32> G;
+ BitField<4, 1, u32> B;
+ BitField<5, 1, u32> A;
+ BitField<6, 4, u32> RT;
+ BitField<10, 16, u32> layer;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x5);
+ struct ReportSemaphore {
+ struct Compare {
+ u32 initial_sequence;
+ u32 initial_mode;
+ u32 unknown1;
+ u32 unknown2;
+ u32 current_sequence;
+ u32 current_mode;
+ };
- INSERT_PADDING_WORDS_NOINIT(0x1F);
+ enum class Operation : u32 {
+ Release = 0,
+ Acquire = 1,
+ ReportOnly = 2,
+ Trap = 3,
+ };
- float polygon_offset_clamp;
+ enum class Release : u32 {
+ AfterAllPreceedingReads = 0,
+ AfterAllPreceedingWrites = 1,
+ };
- struct {
- u32 is_instanced[NumVertexArrays];
+ enum class Acquire : u32 {
+ BeforeAnyFollowingWrites = 0,
+ BeforeAnyFollowingReads = 1,
+ };
- /// Returns whether the vertex array specified by index is supposed to be
- /// accessed per instance or not.
- bool IsInstancingEnabled(std::size_t index) const {
- return is_instanced[index];
- }
- } instanced_arrays;
+ enum class Location : u32 {
+ None = 0,
+ VertexFetch = 1,
+ VertexShader = 2,
+ VPC = 4,
+ StreamingOutput = 5,
+ GeometryShader = 6,
+ ZCull = 7,
+ TessellationInit = 8,
+ TessellationShader = 9,
+ PixelShader = 10,
+ DepthTest = 12,
+ All = 15,
+ };
- INSERT_PADDING_WORDS_NOINIT(0x4);
+ enum class Comparison : u32 {
+ NotEqual = 0,
+ GreaterOrEqual = 1,
+ };
- union {
- BitField<0, 1, u32> enable;
- BitField<4, 8, u32> unk4;
- } vp_point_size;
+ enum class Report : u32 {
+ Payload = 0, // "None" in docs, but confirmed via hardware to return the payload
+ VerticesGenerated = 1,
+ ZPassPixelCount = 2,
+ PrimitivesGenerated = 3,
+ AlphaBetaClocks = 4,
+ VertexShaderInvocations = 5,
+ StreamingPrimitivesNeededMinusSucceeded = 6,
+ GeometryShaderInvocations = 7,
+ GeometryShaderPrimitivesGenerated = 9,
+ ZCullStats0 = 10,
+ StreamingPrimitivesSucceeded = 11,
+ ZCullStats1 = 12,
+ StreamingPrimitivesNeeded = 13,
+ ZCullStats2 = 14,
+ ClipperInvocations = 15,
+ ZCullStats3 = 16,
+ ClipperPrimitivesGenerated = 17,
+ VtgPrimitivesOut = 18,
+ PixelShaderInvocations = 19,
+ ZPassPixelCount64 = 21,
+ IEEECleanColorTarget = 24,
+ IEEECleanZetaTarget = 25,
+ StreamingByteCount = 26,
+ TessellationInitInvocations = 27,
+ BoundingRectangle = 28,
+ TessellationShaderInvocations = 29,
+ TotalStreamingPrimitivesNeededMinusSucceeded = 30,
+ TessellationShaderPrimitivesGenerated = 31,
+ };
- INSERT_PADDING_WORDS_NOINIT(1);
+ u32 address_high;
+ u32 address_low;
+ u32 payload;
+ union {
+ u32 raw;
+ BitField<0, 2, Operation> operation;
+ BitField<4, 1, Release> release;
+ BitField<8, 1, Acquire> acquire;
+ BitField<12, 4, Location> location;
+ BitField<16, 1, Comparison> comparison;
+ BitField<20, 1, u32> awaken_enable;
+ BitField<23, 5, Report> report;
+ BitField<28, 1, u32> short_query;
+ BitField<5, 3, u32> sub_report;
+ BitField<21, 1, u32> dword_number;
+ BitField<2, 1, u32> disable_flush;
+ BitField<3, 1, u32> reduction_enable;
+ BitField<9, 3, ReductionOp> reduction_op;
+ BitField<17, 2, u32> format_signed;
+ } query;
- u32 cull_test_enabled;
- FrontFace front_face;
- CullFace cull_face;
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
+ };
- u32 pixel_center_integer;
+ struct VertexStream {
+ union {
+ BitField<0, 12, u32> stride;
+ BitField<12, 1, u32> enable;
+ };
+ u32 address_high;
+ u32 address_low;
+ u32 frequency;
- INSERT_PADDING_WORDS_NOINIT(0x1);
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
- u32 viewport_transform_enabled;
+ bool IsEnabled() const {
+ return enable != 0 && Address() != 0;
+ }
+ };
+ static_assert(sizeof(VertexStream) == 0x10);
- INSERT_PADDING_WORDS_NOINIT(0x3);
+ struct VertexStreamLimit {
+ u32 address_high;
+ u32 address_low;
- union {
- BitField<0, 1, u32> depth_range_0_1;
- BitField<3, 1, u32> depth_clamp_near;
- BitField<4, 1, u32> depth_clamp_far;
- BitField<11, 1, u32> depth_clamp_disabled;
- } view_volume_clip_control;
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
+ };
+ static_assert(sizeof(VertexStreamLimit) == 0x8);
- INSERT_PADDING_WORDS_NOINIT(0xC);
+ enum class ShaderType : u32 {
+ VertexA = 0,
+ VertexB = 1,
+ TessellationInit = 2,
+ Tessellation = 3,
+ Geometry = 4,
+ Pixel = 5,
+ };
- PrimitiveTopologyOverride topology_override;
+ struct Pipeline {
+ union {
+ BitField<0, 1, u32> enable;
+ BitField<4, 4, ShaderType> program;
+ };
+ u32 offset;
+ u32 reservedA;
+ u32 register_count;
+ u32 binding_group;
+ std::array<u32, 4> reserved;
+ INSERT_PADDING_BYTES_NOINIT(0x1C);
+ };
+ static_assert(sizeof(Pipeline) == 0x40);
- INSERT_PADDING_WORDS_NOINIT(0x12);
+ bool IsShaderConfigEnabled(std::size_t index) const {
+ // The VertexB is always enabled.
+ if (index == static_cast<std::size_t>(ShaderType::VertexB)) {
+ return true;
+ }
+ return pipelines[index].enable != 0;
+ }
- u32 depth_bounds_enable;
+ bool IsShaderConfigEnabled(ShaderType type) const {
+ return IsShaderConfigEnabled(static_cast<std::size_t>(type));
+ }
- INSERT_PADDING_WORDS_NOINIT(1);
+ struct ConstantBuffer {
+ u32 size;
+ u32 address_high;
+ u32 address_low;
+ u32 offset;
+ std::array<u32, NumCBData> buffer;
- struct {
- u32 enable;
- LogicOperation operation;
- } logic_op;
+ GPUVAddr Address() const {
+ return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
+ address_low);
+ }
+ };
- INSERT_PADDING_WORDS_NOINIT(0x1);
+ struct BindGroup {
+ std::array<u32, 4> reserved;
+ union {
+ u32 raw_config;
+ BitField<0, 1, u32> valid;
+ BitField<4, 5, u32> shader_slot;
+ };
+ INSERT_PADDING_BYTES_NOINIT(0xC);
+ };
+ static_assert(sizeof(BindGroup) == 0x20);
+ struct StreamOutLayout {
+ union {
+ BitField<0, 8, u32> attribute0;
+ BitField<8, 8, u32> attribute1;
+ BitField<16, 8, u32> attribute2;
+ BitField<24, 8, u32> attribute3;
+ };
+ };
+
+ struct ShaderPerformance {
+ struct ControlA {
union {
- u32 raw;
- BitField<0, 1, u32> Z;
- BitField<1, 1, u32> S;
- BitField<2, 1, u32> R;
- BitField<3, 1, u32> G;
- BitField<4, 1, u32> B;
- BitField<5, 1, u32> A;
- BitField<6, 4, u32> RT;
- BitField<10, 11, u32> layer;
- } clear_buffers;
- INSERT_PADDING_WORDS_NOINIT(0xB);
- std::array<ColorMask, NumRenderTargets> color_mask;
- INSERT_PADDING_WORDS_NOINIT(0x38);
-
- struct {
- u32 query_address_high;
- u32 query_address_low;
- u32 query_sequence;
- union {
- u32 raw;
- BitField<0, 2, QueryOperation> operation;
- BitField<4, 1, u32> fence;
- BitField<12, 4, QueryUnit> unit;
- BitField<16, 1, QuerySyncCondition> sync_cond;
- BitField<23, 5, QuerySelect> select;
- BitField<28, 1, u32> short_query;
- } query_get;
-
- GPUVAddr QueryAddress() const {
- return static_cast<GPUVAddr>(
- (static_cast<GPUVAddr>(query_address_high) << 32) | query_address_low);
- }
- } query;
-
- INSERT_PADDING_WORDS_NOINIT(0x3C);
-
- struct {
- union {
- BitField<0, 12, u32> stride;
- BitField<12, 1, u32> enable;
- };
- u32 start_high;
- u32 start_low;
- u32 divisor;
-
- GPUVAddr StartAddress() const {
- return static_cast<GPUVAddr>((static_cast<GPUVAddr>(start_high) << 32) |
- start_low);
- }
-
- bool IsEnabled() const {
- return enable != 0 && StartAddress() != 0;
- }
-
- } vertex_array[NumVertexArrays];
-
- Blend independent_blend[NumRenderTargets];
-
- struct {
- u32 limit_high;
- u32 limit_low;
-
- GPUVAddr LimitAddress() const {
- return static_cast<GPUVAddr>((static_cast<GPUVAddr>(limit_high) << 32) |
- limit_low);
- }
- } vertex_array_limit[NumVertexArrays];
-
- struct {
- union {
- BitField<0, 1, u32> enable;
- BitField<4, 4, ShaderProgram> program;
- };
- u32 offset;
- INSERT_PADDING_WORDS_NOINIT(14);
- } shader_config[MaxShaderProgram];
-
- INSERT_PADDING_WORDS_NOINIT(0x60);
-
- u32 firmware[0x20];
-
- struct {
- u32 cb_size;
- u32 cb_address_high;
- u32 cb_address_low;
- u32 cb_pos;
- std::array<u32, NumCBData> cb_data;
-
- GPUVAddr BufferAddress() const {
- return static_cast<GPUVAddr>(
- (static_cast<GPUVAddr>(cb_address_high) << 32) | cb_address_low);
- }
- } const_buffer;
-
- INSERT_PADDING_WORDS_NOINIT(0x10);
-
- struct {
- union {
- u32 raw_config;
- BitField<0, 1, u32> valid;
- BitField<4, 5, u32> index;
- };
- INSERT_PADDING_WORDS_NOINIT(7);
- } cb_bind[MaxShaderStage];
-
- INSERT_PADDING_WORDS_NOINIT(0x56);
-
- u32 tex_cb_index;
-
- INSERT_PADDING_WORDS_NOINIT(0x7D);
-
- std::array<std::array<u8, 128>, NumTransformFeedbackBuffers> tfb_varying_locs;
-
- INSERT_PADDING_WORDS_NOINIT(0x298);
-
- struct {
- /// Compressed address of a buffer that holds information about bound SSBOs.
- /// This address is usually bound to c0 in the shaders.
- u32 buffer_address;
-
- GPUVAddr BufferAddress() const {
- return static_cast<GPUVAddr>(buffer_address) << 8;
- }
- } ssbo_info;
+ BitField<0, 2, u32> event0;
+ BitField<2, 3, u32> bit0;
+ BitField<5, 2, u32> event1;
+ BitField<7, 3, u32> bit1;
+ BitField<10, 2, u32> event2;
+ BitField<12, 3, u32> bit2;
+ BitField<15, 2, u32> event3;
+ BitField<17, 3, u32> bit3;
+ BitField<20, 2, u32> event4;
+ BitField<22, 3, u32> bit4;
+ BitField<25, 2, u32> event5;
+ BitField<27, 3, u32> bit5;
+ BitField<30, 2, u32> spare;
+ };
+ };
- INSERT_PADDING_WORDS_NOINIT(0x11);
+ struct ControlB {
+ union {
+ BitField<0, 1, u32> edge;
+ BitField<1, 2, u32> mode;
+ BitField<3, 1, u32> windowed;
+ BitField<4, 16, u32> func;
+ };
+ };
- struct {
- u32 address[MaxShaderStage];
- u32 size[MaxShaderStage];
- } tex_info_buffers;
+ std::array<u32, 8> values_upper;
+ std::array<u32, 8> values;
+ std::array<u32, 8> events;
+ std::array<ControlA, 8> control_a;
+ std::array<ControlB, 8> control_b;
+ u32 trap_control_mask;
+ u32 start_shader_mask;
+ u32 stop_shader_mask;
+ };
- INSERT_PADDING_WORDS_NOINIT(0xCC);
+ // clang-format off
+ union {
+ struct {
+ ID object_id; ///< 0x0000
+ INSERT_PADDING_BYTES_NOINIT(0xFC);
+ u32 nop; ///< 0x0100
+ Notify notify; ///< 0x0104
+ u32 wait_for_idle; ///< 0x0110
+ LoadMME load_mme; ///< 0x0114
+ ShadowRamControl shadow_ram_control; ///< 0x0124
+ PeerSemaphore peer; ///< 0x0128
+ GlobalRender global_render; ///< 0x0130
+ u32 go_idle; ///< 0x013C
+ u32 trigger; ///< 0x0140
+ u32 trigger_wfi; ///< 0x0144
+ INSERT_PADDING_BYTES_NOINIT(0x8);
+ u32 instrumentation_method_header; ///< 0x0150
+ u32 instrumentation_method_data; ///< 0x0154
+ INSERT_PADDING_BYTES_NOINIT(0x28);
+ Upload::Registers upload; ///< 0x0180
+ LaunchDMA launch_dma; ///< 0x01B0
+ u32 inline_data; ///< 0x01B4
+ INSERT_PADDING_BYTES_NOINIT(0x24);
+ I2M i2m; ///< 0x01DC
+ u32 run_ds_now; ///< 0x0200
+ OpportunisticEarlyZ opportunistic_early_z; ///< 0x0204
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u32 aliased_line_width_enabled; ///< 0x020C
+ u32 mandated_early_z; ///< 0x0210
+ GeometryShaderDmFifo gs_dm_fifo; ///< 0x0214
+ L2CacheControl l2_cache_control; ///< 0x0218
+ InvalidateShaderCache invalidate_shader_cache; ///< 0x021C
+ INSERT_PADDING_BYTES_NOINIT(0xA8);
+ SyncInfo sync_info; ///< 0x02C8
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u32 prim_circular_buffer_throttle; ///< 0x02D0
+ u32 flush_invalidate_rop_mini_cache; ///< 0x02D4
+ SurfaceClipBlockId surface_clip_block_id; ///< 0x02D8
+ u32 alpha_circular_buffer_size; ///< 0x02DC
+ DecompressSurface decompress_surface; ///< 0x02E0
+ ZCullRopBypass zcull_rop_bypass; ///< 0x02E4
+ ZCullSubregion zcull_subregion; ///< 0x02E8
+ RasterBoundingBox raster_bounding_box; ///< 0x02EC
+ u32 peer_semaphore_release; ///< 0x02F0
+ u32 iterated_blend_optimization; ///< 0x02F4
+ ZCullSubregionAllocation zcull_subregion_allocation; ///< 0x02F8
+ ZCullSubregionAlgorithm zcull_subregion_algorithm; ///< 0x02FC
+ PixelShaderOutputSampleMaskUsage ps_output_sample_mask_usage; ///< 0x0300
+ u32 draw_zero_index; ///< 0x0304
+ L1Configuration l1_configuration; ///< 0x0308
+ u32 render_enable_control_load_const_buffer; ///< 0x030C
+ SPAVersion spa_version; ///< 0x0310
+ u32 ieee_clean_update; ///< 0x0314
+ SnapGrid snap_grid; ///< 0x0318
+ Tessellation tessellation; ///< 0x0320
+ SubTilingPerf sub_tiling_perf; ///< 0x0360
+ ZCullSubregionReport zcull_subregion_report; ///< 0x036C
+ BalancedPrimitiveWorkload balanced_primitive_workload; ///< 0x0374
+ u32 max_patches_per_batch; ///< 0x0378
+ u32 rasterize_enable; ///< 0x037C
+ TransformFeedback transform_feedback; ///< 0x0380
+ u32 raster_input; ///< 0x0740
+ u32 transform_feedback_enabled; ///< 0x0744
+ u32 primitive_restart_topology_change_enable; ///< 0x0748
+ u32 alpha_fraction; ///< 0x074C
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ HybridAntiAliasControl hybrid_aa_control; ///< 0x0754
+ INSERT_PADDING_BYTES_NOINIT(0x24);
+ ShaderLocalMemory shader_local_memory; ///< 0x077C
+ u32 color_zero_bandwidth_clear; ///< 0x07A4
+ u32 z_zero_bandwidth_clear; ///< 0x07A8
+ u32 isbe_save_restore_program_offset; ///< 0x07AC
+ INSERT_PADDING_BYTES_NOINIT(0x10);
+ ZCullRegion zcull_region; ///< 0x07C0
+ ZetaReadOnly zeta_read_only; ///< 0x07F8
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ std::array<RenderTargetConfig, NumRenderTargets> rt; ///< 0x0800
+ std::array<ViewportTransform, NumViewports> viewport_transform; ///< 0x0A00
+ std::array<Viewport, NumViewports> viewports; ///< 0x0C00
+ std::array<Window, 8> windows; ///< 0x0D00
+ std::array<ClipIdExtent, 4> clip_id_extent; ///< 0x0D40
+ u32 max_geometry_instances_per_task; ///< 0x0D60
+ VisibleCallLimit visible_call_limit; ///< 0x0D64
+ StatisticsCounter statistics_count; ///< 0x0D68
+ ClearRect clear_rect; ///< 0x0D6C
+ VertexBuffer vertex_buffer; ///< 0x0D74
+ DepthMode depth_mode; ///< 0x0D7C
+ std::array<f32, 4> clear_color; ///< 0x0D80
+ f32 clear_depth; ///< 0x0D90
+ u32 shader_cache_icache_prefetch; ///< 0x0D94
+ u32 force_transition_to_beta; ///< 0x0D98
+ u32 reduce_colour_thresholds; ///< 0x0D9C
+ s32 clear_stencil; ///< 0x0DA0
+ InvalidateShaderCacheNoWFI invalidate_shader_cache_no_wfi; ///< 0x0DA4
+ ZCullSerialization zcull_serialization; ///< 0x0DA8
+ PolygonMode polygon_mode_front; ///< 0x0DAC
+ PolygonMode polygon_mode_back; ///< 0x0DB0
+ u32 polygon_smooth; ///< 0x0DB4
+ u32 zeta_mark_clean_ieee; ///< 0x0DB8
+ ZCullDirFormat zcull_dir_format; ///< 0x0DBC
+ u32 polygon_offset_point_enable; ///< 0x0DC0
+ u32 polygon_offset_line_enable; ///< 0x0DC4
+ u32 polygon_offset_fill_enable; ///< 0x0DC8
+ u32 patch_vertices; ///< 0x0DCC
+ IteratedBlend iterated_blend; ///< 0x0DD0
+ ZCullCriterion zcull_criteria; ///< 0x0DD8
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u32 fragment_barrier; ///< 0x0DE0
+ u32 sm_timeout; ///< 0x0DE4
+ u32 primitive_restart_array; ///< 0x0DE8
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ LoadIteratedBlend load_iterated_blend; ///< 0x0DF0
+ u32 window_offset_x; ///< 0x0DF8
+ u32 window_offset_y; ///< 0x0DFC
+ std::array<ScissorTest, NumViewports> scissor_test; ///< 0x0E00
+ INSERT_PADDING_BYTES_NOINIT(0x10);
+ u32 select_texture_headers; ///< 0x0F10
+ VPCPerf vpc_perf; ///< 0x0F14
+ u32 pm_local_trigger; ///< 0x0F18
+ u32 post_z_pixel_imask; ///< 0x0F1C
+ INSERT_PADDING_BYTES_NOINIT(0x20);
+ ConstantColorRendering const_color_rendering; ///< 0x0F40
+ s32 stencil_back_ref; ///< 0x0F54
+ u32 stencil_back_mask; ///< 0x0F58
+ u32 stencil_back_func_mask; ///< 0x0F5C
+ INSERT_PADDING_BYTES_NOINIT(0x24);
+ VertexStreamSubstitute vertex_stream_substitute; ///< 0x0F84
+ u32 line_mode_clip_generated_edge_do_not_draw; ///< 0x0F8C
+ u32 color_mask_common; ///< 0x0F90
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ VTGWarpWatermarks vtg_warp_watermarks; ///< 0x0F98
+ f32 depth_bounds[2]; ///< 0x0F9C
+ SampleMask::Target sample_mask_target; ///< 0x0FA4
+ u32 color_target_mrt_enable; ///< 0x0FAC
+ NonMultisampledZ non_multisampled_z; ///< 0x0FB0
+ TIRMode tir_mode; ///< 0x0FB4
+ AntiAliasRaster anti_alias_raster; ///< 0x0FB8
+ SampleMask::Pos sample_mask_pos; ///< 0x0FBC
+ SurfaceClipIDMemory surface_clip_id_memory; ///< 0x0FCC
+ TIRModulation tir_modulation; ///< 0x0FD4
+ u32 blend_control_allow_float_pixel_kills; ///< 0x0FDC
+ Zeta zeta; ///< 0x0FE0
+ SurfaceClip surface_clip; ///< 0x0FF4
+ u32 tiled_cache_treat_heavy_as_light; ///< 0x0FFC
+ L2CacheVAFRequests l2_cache_vaf; ///< 0x1000
+ ViewportMulticast viewport_multicast; ///< 0x1004
+ u32 tessellation_cut_height; ///< 0x1008
+ u32 max_gs_instances_per_task; ///< 0x100C
+ u32 max_gs_output_vertices_per_task; ///< 0x1010
+ u32 reserved_sw_method0; ///< 0x1014
+ u32 gs_output_cb_storage_multiplier; ///< 0x1018
+ u32 beta_cb_storage_constant; ///< 0x101C
+ u32 ti_output_cb_storage_multiplier; ///< 0x1020
+ u32 alpha_cb_storage_constraint; ///< 0x1024
+ u32 reserved_sw_method1; ///< 0x1028
+ u32 reserved_sw_method2; ///< 0x102C
+ std::array<TIRModulationCoeff, 5> tir_modulation_coeff; ///< 0x1030
+ std::array<u32, 15> spare_nop; ///< 0x1044
+ INSERT_PADDING_BYTES_NOINIT(0x30);
+ std::array<u32, 7> reserved_sw_method3_to_7; ///< 0x10B0
+ ReduceColorThreshold reduce_color_thresholds_unorm8; ///< 0x10CC
+ std::array<u32, 4> reserved_sw_method10_to_13; ///< 0x10D0
+ ReduceColorThreshold reduce_color_thresholds_unorm10; ///< 0x10E0
+ ReduceColorThreshold reduce_color_thresholds_unorm16; ///< 0x10E4
+ ReduceColorThreshold reduce_color_thresholds_fp11; ///< 0x10E8
+ ReduceColorThreshold reduce_color_thresholds_fp16; ///< 0x10EC
+ ReduceColorThreshold reduce_color_thresholds_srgb8; ///< 0x10F0
+ u32 unbind_all_constant_buffers; ///< 0x10F4
+ ClearControl clear_control; ///< 0x10F8
+ L2CacheRopNonInterlockedReads l2_cache_rop_non_interlocked_reads; ///< 0x10FC
+ u32 reserved_sw_method14; ///< 0x1100
+ u32 reserved_sw_method15; ///< 0x1104
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u32 no_operation_data_high; ///< 0x110C
+ u32 depth_bias_control; ///< 0x1110
+ u32 pm_trigger_end; ///< 0x1114
+ u32 vertex_id_base; ///< 0x1118
+ u32 stencil_compression_enabled; ///< 0x111C
+ VertexOutputAttributeSkipMasks vertex_output_attribute_skip_masks; ///< 0x1120
+ TIRControl tir_control; ///< 0x1130
+ u32 mutable_method_treat_mutable_as_heavy; ///< 0x1134
+ u32 post_ps_use_pre_ps_coverage; ///< 0x1138
+ FillViaTriangleMode fill_via_triangle_mode; ///< 0x113C
+ u32 blend_per_format_snorm8_unorm16_snorm16_enabled; ///< 0x1140
+ u32 flush_pending_writes_sm_gloal_store; ///< 0x1144
+ INSERT_PADDING_BYTES_NOINIT(0x18);
+ std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format; ///< 0x1160
+ std::array<MsaaSampleLocation, 4> multisample_sample_locations; ///< 0x11E0
+ u32 offset_render_target_index_by_viewport_index; ///< 0x11F0
+ u32 force_heavy_method_sync; ///< 0x11F4
+ MultisampleCoverageToColor multisample_coverage_to_color; ///< 0x11F8
+ DecompressZetaSurface decompress_zeta_surface; ///< 0x11FC
+ INSERT_PADDING_BYTES_NOINIT(0x8);
+ ZetaSparse zeta_sparse; ///< 0x1208
+ u32 invalidate_sampler_cache; ///< 0x120C
+ u32 invalidate_texture_header_cache; ///< 0x1210
+ VertexArray vertex_array_instance_first; ///< 0x1214
+ VertexArray vertex_array_instance_subsequent; ///< 0x1218
+ RtControl rt_control; ///< 0x121C
+ CompressionThresholdSamples compression_threshold_samples; ///< 0x1220
+ PixelShaderInterlockControl ps_interlock_control; ///< 0x1224
+ ZetaSize zeta_size; ///< 0x1228
+ SamplerBinding sampler_binding; ///< 0x1234
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u32 draw_auto_byte_count; ///< 0x123C
+ std::array<u32, 8> post_vtg_shader_attrib_skip_mask; ///< 0x1240
+ PsTicketDispenserValue ps_ticket_dispenser_value; ///< 0x1260
+ INSERT_PADDING_BYTES_NOINIT(0x1C);
+ u32 circular_buffer_size; ///< 0x1280
+ RegisterWatermarks vtg_register_watermarks; ///< 0x1284
+ InvalidateTextureDataCacheNoWfi invalidate_texture_cache_no_wfi; ///< 0x1288
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ L2CacheRopNonInterlockedReads l2_cache_rop_interlocked_reads; ///< 0x1290
+ INSERT_PADDING_BYTES_NOINIT(0x10);
+ u32 primitive_restart_topology_change_index; ///< 0x12A4
+ INSERT_PADDING_BYTES_NOINIT(0x20);
+ ZCullRegionEnable zcull_region_enable; ///< 0x12C8
+ u32 depth_test_enable; ///< 0x12CC
+ FillMode fill_mode; ///< 0x12D0
+ ShadeMode shade_mode; ///< 0x12D4
+ L2CacheRopNonInterlockedReads l2_cache_rop_non_interlocked_writes; ///< 0x12D8
+ L2CacheRopNonInterlockedReads l2_cache_rop_interlocked_writes; ///< 0x12DC
+ AlphaToCoverageDither alpha_to_coverage_dither; ///< 0x12E0
+ u32 blend_per_target_enabled; ///< 0x12E4
+ u32 depth_write_enabled; ///< 0x12E8
+ u32 alpha_test_enabled; ///< 0x12EC
+ INSERT_PADDING_BYTES_NOINIT(0x10);
+ InlineIndex4x8Align inline_index_4x8_align; ///< 0x1300
+ InlineIndex4x8Index inline_index_4x8_index; ///< 0x1304
+ D3DCullMode d3d_cull_mode; ///< 0x1308
+ ComparisonOp depth_test_func; ///< 0x130C
+ f32 alpha_test_ref; ///< 0x1310
+ ComparisonOp alpha_test_func; ///< 0x1314
+ u32 draw_auto_stride; ///< 0x1318
+ BlendColor blend_color; ///< 0x131C
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ InvalidateCacheLines invalidate_sampler_cache_lines; ///< 0x1330
+ InvalidateCacheLines invalidate_texture_header_cache_lines; ///< 0x1334
+ InvalidateCacheLines invalidate_texture_data_cache_lines; ///< 0x1338
+ Blend blend; ///< 0x133C
+ u32 stencil_enable; ///< 0x1380
+ StencilOp stencil_front_op; ///< 0x1384
+ s32 stencil_front_ref; ///< 0x1394
+ s32 stencil_front_func_mask; ///< 0x1398
+ s32 stencil_front_mask; ///< 0x139C
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u32 draw_auto_start_byte_count; ///< 0x13A4
+ PsSaturate frag_color_clamp; ///< 0x13A8
+ WindowOrigin window_origin; ///< 0x13AC
+ f32 line_width_smooth; ///< 0x13B0
+ f32 line_width_aliased; ///< 0x13B4
+ INSERT_PADDING_BYTES_NOINIT(0x60);
+ u32 line_override_multisample; ///< 0x1418
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u32 alpha_hysteresis_rounds; ///< 0x1420
+ InvalidateCacheLines invalidate_sampler_cache_no_wfi; ///< 0x1424
+ InvalidateCacheLines invalidate_texture_header_cache_no_wfi; ///< 0x1428
+ INSERT_PADDING_BYTES_NOINIT(0x8);
+ u32 global_base_vertex_index; ///< 0x1434
+ u32 global_base_instance_index; ///< 0x1438
+ INSERT_PADDING_BYTES_NOINIT(0x14);
+ RegisterWatermarks ps_warp_watermarks; ///< 0x1450
+ RegisterWatermarks ps_regster_watermarks; ///< 0x1454
+ INSERT_PADDING_BYTES_NOINIT(0xC);
+ u32 store_zcull; ///< 0x1464
+ INSERT_PADDING_BYTES_NOINIT(0x18);
+ std::array<IteratedBlendConstants, NumRenderTargets>
+ iterated_blend_constants; ///< 0x1480
+ u32 load_zcull; ///< 0x1500
+ u32 surface_clip_id_height; ///< 0x1504
+ Window surface_clip_id_clear_rect; ///< 0x1508
+ UserClip::Enable user_clip_enable; ///< 0x1510
+ u32 zpass_pixel_count_enable; ///< 0x1514
+ f32 point_size; ///< 0x1518
+ u32 zcull_stats_enable; ///< 0x151C
+ u32 point_sprite_enable; ///< 0x1520
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u32 shader_exceptions_enable; ///< 0x1528
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ ClearReport clear_report_value; ///< 0x1530
+ u32 anti_alias_enable; ///< 0x1534
+ u32 zeta_enable; ///< 0x1538
+ AntiAliasAlphaControl anti_alias_alpha_control; ///< 0x153C
+ INSERT_PADDING_BYTES_NOINIT(0x10);
+ RenderEnable render_enable; ///< 0x1550
+ TexSampler tex_sampler; ///< 0x155C
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ f32 slope_scale_depth_bias; ///< 0x156C
+ u32 line_anti_alias_enable; ///< 0x1570
+ TexHeader tex_header; ///< 0x1574
+ INSERT_PADDING_BYTES_NOINIT(0x10);
+ u32 active_zcull_region_id; ///< 0x1590
+ u32 stencil_two_side_enable; ///< 0x1594
+ StencilOp stencil_back_op; ///< 0x1598
+ INSERT_PADDING_BYTES_NOINIT(0x10);
+ u32 framebuffer_srgb; ///< 0x15B8
+ f32 depth_bias; ///< 0x15BC
+ INSERT_PADDING_BYTES_NOINIT(0x8);
+ ZCullRegionFormat zcull_region_format; ///< 0x15C8
+ RtLayer rt_layer; ///< 0x15CC
+ Tegra::Texture::MsaaMode anti_alias_samples_mode; ///< 0x15D0
+ INSERT_PADDING_BYTES_NOINIT(0x10);
+ u32 edge_flag; ///< 0x15E4
+ u32 draw_inline_index; ///< 0x15E8
+ InlineIndex2x16 inline_index_2x16; ///< 0x15EC
+ VertexGlobalBaseOffset vertex_global_base_offset; ///< 0x15F4
+ ZCullRegionPixelOffset zcull_region_pixel_offset; ///< 0x15FC
+ PointSprite point_sprite; ///< 0x1604
+ ProgramRegion program_region; ///< 0x1608
+ DefaultAttributes default_attributes; ///< 0x1610
+ Draw draw; ///< 0x1614
+ VertexIdCopy vertex_id_copy; ///< 0x161C
+ u32 add_to_primitive_id; ///< 0x1620
+ u32 load_to_primitive_id; ///< 0x1624
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ ShaderBasedCull shader_based_cull; ///< 0x162C
+ INSERT_PADDING_BYTES_NOINIT(0x8);
+ ClassVersion class_version; ///< 0x1638
+ INSERT_PADDING_BYTES_NOINIT(0x8);
+ PrimitiveRestart primitive_restart; ///< 0x1644
+ OutputVertexId output_vertex_id; ///< 0x164C
+ INSERT_PADDING_BYTES_NOINIT(0x8);
+ u32 anti_alias_point_enable; ///< 0x1658
+ PointCenterMode point_center_mode; ///< 0x165C
+ INSERT_PADDING_BYTES_NOINIT(0x8);
+ LineSmoothParams line_smooth_params; ///< 0x1668
+ u32 line_stipple_enable; ///< 0x166C
+ std::array<LineSmoothEdgeTable, 4> line_smooth_edge_table; ///< 0x1670
+ LineStippleParams line_stipple_params; ///< 0x1680
+ ProvokingVertex provoking_vertex; ///< 0x1684
+ u32 two_sided_light_enabled; ///< 0x1688
+ u32 polygon_stipple_enabled; ///< 0x168C
+ ShaderControl shader_control; ///< 0x1690
+ INSERT_PADDING_BYTES_NOINIT(0xC);
+ ClassVersion class_version_check; ///< 0x16A0
+ SphVersion sph_version; ///< 0x16A4
+ SphVersion sph_version_check; ///< 0x16A8
+ INSERT_PADDING_BYTES_NOINIT(0x8);
+ AlphaToCoverageOverride alpha_to_coverage_override; ///< 0x16B4
+ INSERT_PADDING_BYTES_NOINIT(0x48);
+ std::array<u32, 32> polygon_stipple_pattern; ///< 0x1700
+ INSERT_PADDING_BYTES_NOINIT(0x10);
+ AamVersion aam_version; ///< 0x1790
+ AamVersion aam_version_check; ///< 0x1794
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u32 zeta_layer_offset; ///< 0x179C
+ INSERT_PADDING_BYTES_NOINIT(0x28);
+ IndexBuffer index_buffer; ///< 0x17C8
+ IndexBufferSmall index_buffer32_first; ///< 0x17E4
+ IndexBufferSmall index_buffer16_first; ///< 0x17E8
+ IndexBufferSmall index_buffer8_first; ///< 0x17EC
+ IndexBufferSmall index_buffer32_subsequent; ///< 0x17F0
+ IndexBufferSmall index_buffer16_subsequent; ///< 0x17F4
+ IndexBufferSmall index_buffer8_subsequent; ///< 0x17F8
+ INSERT_PADDING_BYTES_NOINIT(0x80);
+ f32 depth_bias_clamp; ///< 0x187C
+ VertexStreamInstances vertex_stream_instances; ///< 0x1880
+ INSERT_PADDING_BYTES_NOINIT(0x10);
+ AttributePointSize point_size_attribute; ///< 0x1910
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u32 gl_cull_test_enabled; ///< 0x1918
+ FrontFace gl_front_face; ///< 0x191C
+ CullFace gl_cull_face; ///< 0x1920
+ Viewport::PixelCenter viewport_pixel_center; ///< 0x1924
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u32 viewport_scale_offset_enbled; ///< 0x192C
+ INSERT_PADDING_BYTES_NOINIT(0xC);
+ ViewportClipControl viewport_clip_control; ///< 0x193C
+ UserClip::Op user_clip_op; ///< 0x1940
+ RenderEnable::Override render_enable_override; ///< 0x1944
+ PrimitiveTopologyControl primitive_topology_control; ///< 0x1948
+ WindowClip window_clip_enable; ///< 0x194C
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ InvalidateZCull invalidate_zcull; ///< 0x1958
+ INSERT_PADDING_BYTES_NOINIT(0xC);
+ ZCull zcull; ///< 0x1968
+ PrimitiveTopologyOverride topology_override; ///< 0x1970
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u32 zcull_sync; ///< 0x1978
+ u32 clip_id_test_enable; ///< 0x197C
+ u32 surface_clip_id_width; ///< 0x1980
+ u32 clip_id; ///< 0x1984
+ INSERT_PADDING_BYTES_NOINIT(0x34);
+ u32 depth_bounds_enable; ///< 0x19BC
+ u32 blend_float_zero_times_anything_is_zero; ///< 0x19C0
+ LogicOp logic_op; ///< 0x19C4
+ u32 z_compression_enable; ///< 0x19CC
+ ClearSurface clear_surface; ///< 0x19D0
+ u32 clear_clip_id_surface; ///< 0x19D4
+ INSERT_PADDING_BYTES_NOINIT(0x8);
+ std::array<u32, NumRenderTargets> color_compression_enable; ///< 0x19E0
+ std::array<ColorMask, NumRenderTargets> color_mask; ///< 0x1A00
+ INSERT_PADDING_BYTES_NOINIT(0xC);
+ u32 pipe_nop; ///< 0x1A2C
+ std::array<u32, 4> spare; ///< 0x1A30
+ INSERT_PADDING_BYTES_NOINIT(0xC0);
+ ReportSemaphore report_semaphore; ///< 0x1B00
+ INSERT_PADDING_BYTES_NOINIT(0xF0);
+ std::array<VertexStream, NumVertexArrays> vertex_streams; ///< 0x1C00
+ BlendPerTarget blend_per_target[NumRenderTargets]; ///< 0x1E00
+ std::array<VertexStreamLimit, NumVertexArrays> vertex_stream_limits; ///< 0x1F00
+ std::array<Pipeline, MaxShaderProgram> pipelines; ///< 0x2000
+ INSERT_PADDING_BYTES_NOINIT(0x180);
+ u32 falcon[32]; ///< 0x2300
+ ConstantBuffer const_buffer; ///< 0x2380
+ INSERT_PADDING_BYTES_NOINIT(0x30);
+ BindGroup bind_groups[MaxShaderStage]; ///< 0x2400
+ INSERT_PADDING_BYTES_NOINIT(0x160);
+ u32 color_clamp_enable; ///< 0x2600
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u32 bindless_texture_const_buffer_slot; ///< 0x2608
+ u32 trap_handler; ///< 0x260C
+ INSERT_PADDING_BYTES_NOINIT(0x1F0);
+ std::array<std::array<StreamOutLayout, 32>, NumTransformFeedbackBuffers>
+ stream_out_layout; ///< 0x2800
+ INSERT_PADDING_BYTES_NOINIT(0x93C);
+ ShaderPerformance shader_performance; ///< 0x333C
+ INSERT_PADDING_BYTES_NOINIT(0x18);
+ std::array<u32, 0x100> shadow_scratch; ///< 0x3400
};
std::array<u32, NUM_REGS> reg_array;
};
};
+ // clang-format on
Regs regs{};
@@ -1591,147 +3201,350 @@ private:
};
#define ASSERT_REG_POSITION(field_name, position) \
- static_assert(offsetof(Maxwell3D::Regs, field_name) == position * 4, \
+ static_assert(offsetof(Maxwell3D::Regs, field_name) == position, \
"Field " #field_name " has invalid position")
-ASSERT_REG_POSITION(wait_for_idle, 0x44);
-ASSERT_REG_POSITION(macros, 0x45);
-ASSERT_REG_POSITION(shadow_ram_control, 0x49);
-ASSERT_REG_POSITION(upload, 0x60);
-ASSERT_REG_POSITION(exec_upload, 0x6C);
-ASSERT_REG_POSITION(data_upload, 0x6D);
-ASSERT_REG_POSITION(force_early_fragment_tests, 0x84);
-ASSERT_REG_POSITION(sync_info, 0xB2);
-ASSERT_REG_POSITION(tess_mode, 0xC8);
-ASSERT_REG_POSITION(tess_level_outer, 0xC9);
-ASSERT_REG_POSITION(tess_level_inner, 0xCD);
-ASSERT_REG_POSITION(rasterize_enable, 0xDF);
-ASSERT_REG_POSITION(tfb_bindings, 0xE0);
-ASSERT_REG_POSITION(tfb_layouts, 0x1C0);
-ASSERT_REG_POSITION(tfb_enabled, 0x1D1);
-ASSERT_REG_POSITION(rt, 0x200);
-ASSERT_REG_POSITION(viewport_transform, 0x280);
-ASSERT_REG_POSITION(viewports, 0x300);
-ASSERT_REG_POSITION(vertex_buffer, 0x35D);
-ASSERT_REG_POSITION(depth_mode, 0x35F);
-ASSERT_REG_POSITION(clear_color[0], 0x360);
-ASSERT_REG_POSITION(clear_depth, 0x364);
-ASSERT_REG_POSITION(clear_stencil, 0x368);
-ASSERT_REG_POSITION(polygon_mode_front, 0x36B);
-ASSERT_REG_POSITION(polygon_mode_back, 0x36C);
-ASSERT_REG_POSITION(polygon_offset_point_enable, 0x370);
-ASSERT_REG_POSITION(polygon_offset_line_enable, 0x371);
-ASSERT_REG_POSITION(polygon_offset_fill_enable, 0x372);
-ASSERT_REG_POSITION(patch_vertices, 0x373);
-ASSERT_REG_POSITION(fragment_barrier, 0x378);
-ASSERT_REG_POSITION(scissor_test, 0x380);
-ASSERT_REG_POSITION(stencil_back_func_ref, 0x3D5);
-ASSERT_REG_POSITION(stencil_back_mask, 0x3D6);
-ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D7);
-ASSERT_REG_POSITION(invalidate_texture_data_cache, 0x3DD);
-ASSERT_REG_POSITION(tiled_cache_barrier, 0x3DF);
-ASSERT_REG_POSITION(color_mask_common, 0x3E4);
-ASSERT_REG_POSITION(depth_bounds, 0x3E7);
-ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB);
-ASSERT_REG_POSITION(multisample_raster_enable, 0x3ED);
-ASSERT_REG_POSITION(multisample_raster_samples, 0x3EE);
-ASSERT_REG_POSITION(multisample_sample_mask, 0x3EF);
-ASSERT_REG_POSITION(zeta, 0x3F8);
-ASSERT_REG_POSITION(render_area, 0x3FD);
-ASSERT_REG_POSITION(clear_flags, 0x43E);
-ASSERT_REG_POSITION(fill_rectangle, 0x44F);
-ASSERT_REG_POSITION(conservative_raster_enable, 0x452);
-ASSERT_REG_POSITION(vertex_attrib_format, 0x458);
-ASSERT_REG_POSITION(multisample_sample_locations, 0x478);
-ASSERT_REG_POSITION(multisample_coverage_to_color, 0x47E);
-ASSERT_REG_POSITION(rt_control, 0x487);
-ASSERT_REG_POSITION(zeta_width, 0x48a);
-ASSERT_REG_POSITION(zeta_height, 0x48b);
-ASSERT_REG_POSITION(zeta_depth, 0x48c);
-ASSERT_REG_POSITION(sampler_index, 0x48D);
-ASSERT_REG_POSITION(gp_passthrough_mask, 0x490);
-ASSERT_REG_POSITION(depth_test_enable, 0x4B3);
-ASSERT_REG_POSITION(independent_blend_enable, 0x4B9);
-ASSERT_REG_POSITION(depth_write_enabled, 0x4BA);
-ASSERT_REG_POSITION(alpha_test_enabled, 0x4BB);
-ASSERT_REG_POSITION(d3d_cull_mode, 0x4C2);
-ASSERT_REG_POSITION(depth_test_func, 0x4C3);
-ASSERT_REG_POSITION(alpha_test_ref, 0x4C4);
-ASSERT_REG_POSITION(alpha_test_func, 0x4C5);
-ASSERT_REG_POSITION(draw_tfb_stride, 0x4C6);
-ASSERT_REG_POSITION(blend_color, 0x4C7);
-ASSERT_REG_POSITION(blend, 0x4CF);
-ASSERT_REG_POSITION(stencil_enable, 0x4E0);
-ASSERT_REG_POSITION(stencil_front_op_fail, 0x4E1);
-ASSERT_REG_POSITION(stencil_front_op_zfail, 0x4E2);
-ASSERT_REG_POSITION(stencil_front_op_zpass, 0x4E3);
-ASSERT_REG_POSITION(stencil_front_func_func, 0x4E4);
-ASSERT_REG_POSITION(stencil_front_func_ref, 0x4E5);
-ASSERT_REG_POSITION(stencil_front_func_mask, 0x4E6);
-ASSERT_REG_POSITION(stencil_front_mask, 0x4E7);
-ASSERT_REG_POSITION(frag_color_clamp, 0x4EA);
-ASSERT_REG_POSITION(screen_y_control, 0x4EB);
-ASSERT_REG_POSITION(line_width_smooth, 0x4EC);
-ASSERT_REG_POSITION(line_width_aliased, 0x4ED);
-ASSERT_REG_POSITION(invalidate_sampler_cache_no_wfi, 0x509);
-ASSERT_REG_POSITION(invalidate_texture_header_cache_no_wfi, 0x50A);
-ASSERT_REG_POSITION(vb_element_base, 0x50D);
-ASSERT_REG_POSITION(vb_base_instance, 0x50E);
-ASSERT_REG_POSITION(clip_distance_enabled, 0x544);
-ASSERT_REG_POSITION(samplecnt_enable, 0x545);
-ASSERT_REG_POSITION(point_size, 0x546);
-ASSERT_REG_POSITION(point_sprite_enable, 0x548);
-ASSERT_REG_POSITION(counter_reset, 0x54C);
-ASSERT_REG_POSITION(multisample_enable, 0x54D);
-ASSERT_REG_POSITION(zeta_enable, 0x54E);
-ASSERT_REG_POSITION(multisample_control, 0x54F);
-ASSERT_REG_POSITION(condition, 0x554);
-ASSERT_REG_POSITION(tsc, 0x557);
-ASSERT_REG_POSITION(polygon_offset_factor, 0x55B);
-ASSERT_REG_POSITION(line_smooth_enable, 0x55C);
-ASSERT_REG_POSITION(tic, 0x55D);
-ASSERT_REG_POSITION(stencil_two_side_enable, 0x565);
-ASSERT_REG_POSITION(stencil_back_op_fail, 0x566);
-ASSERT_REG_POSITION(stencil_back_op_zfail, 0x567);
-ASSERT_REG_POSITION(stencil_back_op_zpass, 0x568);
-ASSERT_REG_POSITION(stencil_back_func_func, 0x569);
-ASSERT_REG_POSITION(framebuffer_srgb, 0x56E);
-ASSERT_REG_POSITION(polygon_offset_units, 0x56F);
-ASSERT_REG_POSITION(multisample_mode, 0x574);
-ASSERT_REG_POSITION(point_coord_replace, 0x581);
-ASSERT_REG_POSITION(code_address, 0x582);
-ASSERT_REG_POSITION(draw, 0x585);
-ASSERT_REG_POSITION(primitive_restart, 0x591);
-ASSERT_REG_POSITION(provoking_vertex_last, 0x5A1);
-ASSERT_REG_POSITION(index_array, 0x5F2);
-ASSERT_REG_POSITION(small_index, 0x5F9);
-ASSERT_REG_POSITION(polygon_offset_clamp, 0x61F);
-ASSERT_REG_POSITION(instanced_arrays, 0x620);
-ASSERT_REG_POSITION(vp_point_size, 0x644);
-ASSERT_REG_POSITION(cull_test_enabled, 0x646);
-ASSERT_REG_POSITION(front_face, 0x647);
-ASSERT_REG_POSITION(cull_face, 0x648);
-ASSERT_REG_POSITION(pixel_center_integer, 0x649);
-ASSERT_REG_POSITION(viewport_transform_enabled, 0x64B);
-ASSERT_REG_POSITION(view_volume_clip_control, 0x64F);
-ASSERT_REG_POSITION(topology_override, 0x65C);
-ASSERT_REG_POSITION(depth_bounds_enable, 0x66F);
-ASSERT_REG_POSITION(logic_op, 0x671);
-ASSERT_REG_POSITION(clear_buffers, 0x674);
-ASSERT_REG_POSITION(color_mask, 0x680);
-ASSERT_REG_POSITION(query, 0x6C0);
-ASSERT_REG_POSITION(vertex_array[0], 0x700);
-ASSERT_REG_POSITION(independent_blend, 0x780);
-ASSERT_REG_POSITION(vertex_array_limit[0], 0x7C0);
-ASSERT_REG_POSITION(shader_config[0], 0x800);
-ASSERT_REG_POSITION(firmware, 0x8C0);
-ASSERT_REG_POSITION(const_buffer, 0x8E0);
-ASSERT_REG_POSITION(cb_bind[0], 0x904);
-ASSERT_REG_POSITION(tex_cb_index, 0x982);
-ASSERT_REG_POSITION(tfb_varying_locs, 0xA00);
-ASSERT_REG_POSITION(ssbo_info, 0xD18);
-ASSERT_REG_POSITION(tex_info_buffers.address[0], 0xD2A);
-ASSERT_REG_POSITION(tex_info_buffers.size[0], 0xD2F);
+ASSERT_REG_POSITION(object_id, 0x0000);
+ASSERT_REG_POSITION(nop, 0x0100);
+ASSERT_REG_POSITION(notify, 0x0104);
+ASSERT_REG_POSITION(wait_for_idle, 0x0110);
+ASSERT_REG_POSITION(load_mme, 0x0114);
+ASSERT_REG_POSITION(shadow_ram_control, 0x0124);
+ASSERT_REG_POSITION(peer, 0x0128);
+ASSERT_REG_POSITION(global_render, 0x0130);
+ASSERT_REG_POSITION(go_idle, 0x013C);
+ASSERT_REG_POSITION(trigger, 0x0140);
+ASSERT_REG_POSITION(trigger_wfi, 0x0144);
+ASSERT_REG_POSITION(instrumentation_method_header, 0x0150);
+ASSERT_REG_POSITION(instrumentation_method_data, 0x0154);
+ASSERT_REG_POSITION(upload, 0x0180);
+ASSERT_REG_POSITION(launch_dma, 0x01B0);
+ASSERT_REG_POSITION(inline_data, 0x01B4);
+ASSERT_REG_POSITION(i2m, 0x01DC);
+ASSERT_REG_POSITION(run_ds_now, 0x0200);
+ASSERT_REG_POSITION(opportunistic_early_z, 0x0204);
+ASSERT_REG_POSITION(aliased_line_width_enabled, 0x020C);
+ASSERT_REG_POSITION(mandated_early_z, 0x0210);
+ASSERT_REG_POSITION(gs_dm_fifo, 0x0214);
+ASSERT_REG_POSITION(l2_cache_control, 0x0218);
+ASSERT_REG_POSITION(invalidate_shader_cache, 0x021C);
+ASSERT_REG_POSITION(sync_info, 0x02C8);
+ASSERT_REG_POSITION(prim_circular_buffer_throttle, 0x02D0);
+ASSERT_REG_POSITION(flush_invalidate_rop_mini_cache, 0x02D4);
+ASSERT_REG_POSITION(surface_clip_block_id, 0x02D8);
+ASSERT_REG_POSITION(alpha_circular_buffer_size, 0x02DC);
+ASSERT_REG_POSITION(decompress_surface, 0x02E0);
+ASSERT_REG_POSITION(zcull_rop_bypass, 0x02E4);
+ASSERT_REG_POSITION(zcull_subregion, 0x02E8);
+ASSERT_REG_POSITION(raster_bounding_box, 0x02EC);
+ASSERT_REG_POSITION(peer_semaphore_release, 0x02F0);
+ASSERT_REG_POSITION(iterated_blend_optimization, 0x02F4);
+ASSERT_REG_POSITION(zcull_subregion_allocation, 0x02F8);
+ASSERT_REG_POSITION(zcull_subregion_algorithm, 0x02FC);
+ASSERT_REG_POSITION(ps_output_sample_mask_usage, 0x0300);
+ASSERT_REG_POSITION(draw_zero_index, 0x0304);
+ASSERT_REG_POSITION(l1_configuration, 0x0308);
+ASSERT_REG_POSITION(render_enable_control_load_const_buffer, 0x030C);
+ASSERT_REG_POSITION(spa_version, 0x0310);
+ASSERT_REG_POSITION(ieee_clean_update, 0x0314);
+ASSERT_REG_POSITION(snap_grid, 0x0318);
+ASSERT_REG_POSITION(tessellation, 0x0320);
+ASSERT_REG_POSITION(sub_tiling_perf, 0x0360);
+ASSERT_REG_POSITION(zcull_subregion_report, 0x036C);
+ASSERT_REG_POSITION(balanced_primitive_workload, 0x0374);
+ASSERT_REG_POSITION(max_patches_per_batch, 0x0378);
+ASSERT_REG_POSITION(rasterize_enable, 0x037C);
+ASSERT_REG_POSITION(transform_feedback, 0x0380);
+ASSERT_REG_POSITION(transform_feedback.controls, 0x0700);
+ASSERT_REG_POSITION(raster_input, 0x0740);
+ASSERT_REG_POSITION(transform_feedback_enabled, 0x0744);
+ASSERT_REG_POSITION(primitive_restart_topology_change_enable, 0x0748);
+ASSERT_REG_POSITION(alpha_fraction, 0x074C);
+ASSERT_REG_POSITION(hybrid_aa_control, 0x0754);
+ASSERT_REG_POSITION(shader_local_memory, 0x077C);
+ASSERT_REG_POSITION(color_zero_bandwidth_clear, 0x07A4);
+ASSERT_REG_POSITION(z_zero_bandwidth_clear, 0x07A8);
+ASSERT_REG_POSITION(isbe_save_restore_program_offset, 0x07AC);
+ASSERT_REG_POSITION(zcull_region, 0x07C0);
+ASSERT_REG_POSITION(zeta_read_only, 0x07F8);
+ASSERT_REG_POSITION(rt, 0x0800);
+ASSERT_REG_POSITION(viewport_transform, 0x0A00);
+ASSERT_REG_POSITION(viewports, 0x0C00);
+ASSERT_REG_POSITION(windows, 0x0D00);
+ASSERT_REG_POSITION(clip_id_extent, 0x0D40);
+ASSERT_REG_POSITION(max_geometry_instances_per_task, 0x0D60);
+ASSERT_REG_POSITION(visible_call_limit, 0x0D64);
+ASSERT_REG_POSITION(statistics_count, 0x0D68);
+ASSERT_REG_POSITION(clear_rect, 0x0D6C);
+ASSERT_REG_POSITION(vertex_buffer, 0x0D74);
+ASSERT_REG_POSITION(depth_mode, 0x0D7C);
+ASSERT_REG_POSITION(clear_color, 0x0D80);
+ASSERT_REG_POSITION(clear_depth, 0x0D90);
+ASSERT_REG_POSITION(shader_cache_icache_prefetch, 0x0D94);
+ASSERT_REG_POSITION(force_transition_to_beta, 0x0D98);
+ASSERT_REG_POSITION(reduce_colour_thresholds, 0x0D9C);
+ASSERT_REG_POSITION(clear_stencil, 0x0DA0);
+ASSERT_REG_POSITION(invalidate_shader_cache_no_wfi, 0x0DA4);
+ASSERT_REG_POSITION(zcull_serialization, 0x0DA8);
+ASSERT_REG_POSITION(polygon_mode_front, 0x0DAC);
+ASSERT_REG_POSITION(polygon_mode_back, 0x0DB0);
+ASSERT_REG_POSITION(polygon_smooth, 0x0DB4);
+ASSERT_REG_POSITION(zeta_mark_clean_ieee, 0x0DB8);
+ASSERT_REG_POSITION(zcull_dir_format, 0x0DBC);
+ASSERT_REG_POSITION(polygon_offset_point_enable, 0x0DC0);
+ASSERT_REG_POSITION(polygon_offset_line_enable, 0x0DC4);
+ASSERT_REG_POSITION(polygon_offset_fill_enable, 0x0DC8);
+ASSERT_REG_POSITION(patch_vertices, 0x0DCC);
+ASSERT_REG_POSITION(iterated_blend, 0x0DD0);
+ASSERT_REG_POSITION(zcull_criteria, 0x0DD8);
+ASSERT_REG_POSITION(fragment_barrier, 0x0DE0);
+ASSERT_REG_POSITION(sm_timeout, 0x0DE4);
+ASSERT_REG_POSITION(primitive_restart_array, 0x0DE8);
+ASSERT_REG_POSITION(load_iterated_blend, 0x0DF0);
+ASSERT_REG_POSITION(window_offset_x, 0x0DF8);
+ASSERT_REG_POSITION(window_offset_y, 0x0DFC);
+ASSERT_REG_POSITION(scissor_test, 0x0E00);
+ASSERT_REG_POSITION(select_texture_headers, 0x0F10);
+ASSERT_REG_POSITION(vpc_perf, 0x0F14);
+ASSERT_REG_POSITION(pm_local_trigger, 0x0F18);
+ASSERT_REG_POSITION(post_z_pixel_imask, 0x0F1C);
+ASSERT_REG_POSITION(const_color_rendering, 0x0F40);
+ASSERT_REG_POSITION(stencil_back_ref, 0x0F54);
+ASSERT_REG_POSITION(stencil_back_mask, 0x0F58);
+ASSERT_REG_POSITION(stencil_back_func_mask, 0x0F5C);
+ASSERT_REG_POSITION(vertex_stream_substitute, 0x0F84);
+ASSERT_REG_POSITION(line_mode_clip_generated_edge_do_not_draw, 0x0F8C);
+ASSERT_REG_POSITION(color_mask_common, 0x0F90);
+ASSERT_REG_POSITION(vtg_warp_watermarks, 0x0F98);
+ASSERT_REG_POSITION(depth_bounds, 0x0F9C);
+ASSERT_REG_POSITION(sample_mask_target, 0x0FA4);
+ASSERT_REG_POSITION(color_target_mrt_enable, 0x0FAC);
+ASSERT_REG_POSITION(non_multisampled_z, 0x0FB0);
+ASSERT_REG_POSITION(tir_mode, 0x0FB4);
+ASSERT_REG_POSITION(anti_alias_raster, 0x0FB8);
+ASSERT_REG_POSITION(sample_mask_pos, 0x0FBC);
+ASSERT_REG_POSITION(surface_clip_id_memory, 0x0FCC);
+ASSERT_REG_POSITION(tir_modulation, 0x0FD4);
+ASSERT_REG_POSITION(blend_control_allow_float_pixel_kills, 0x0FDC);
+ASSERT_REG_POSITION(zeta, 0x0FE0);
+ASSERT_REG_POSITION(surface_clip, 0x0FF4);
+ASSERT_REG_POSITION(tiled_cache_treat_heavy_as_light, 0x0FFC);
+ASSERT_REG_POSITION(l2_cache_vaf, 0x1000);
+ASSERT_REG_POSITION(viewport_multicast, 0x1004);
+ASSERT_REG_POSITION(tessellation_cut_height, 0x1008);
+ASSERT_REG_POSITION(max_gs_instances_per_task, 0x100C);
+ASSERT_REG_POSITION(max_gs_output_vertices_per_task, 0x1010);
+ASSERT_REG_POSITION(reserved_sw_method0, 0x1014);
+ASSERT_REG_POSITION(gs_output_cb_storage_multiplier, 0x1018);
+ASSERT_REG_POSITION(beta_cb_storage_constant, 0x101C);
+ASSERT_REG_POSITION(ti_output_cb_storage_multiplier, 0x1020);
+ASSERT_REG_POSITION(alpha_cb_storage_constraint, 0x1024);
+ASSERT_REG_POSITION(reserved_sw_method1, 0x1028);
+ASSERT_REG_POSITION(reserved_sw_method2, 0x102C);
+ASSERT_REG_POSITION(tir_modulation_coeff, 0x1030);
+ASSERT_REG_POSITION(spare_nop, 0x1044);
+ASSERT_REG_POSITION(reserved_sw_method3_to_7, 0x10B0);
+ASSERT_REG_POSITION(reduce_color_thresholds_unorm8, 0x10CC);
+ASSERT_REG_POSITION(reserved_sw_method10_to_13, 0x10D0);
+ASSERT_REG_POSITION(reduce_color_thresholds_unorm10, 0x10E0);
+ASSERT_REG_POSITION(reduce_color_thresholds_unorm16, 0x10E4);
+ASSERT_REG_POSITION(reduce_color_thresholds_fp11, 0x10E8);
+ASSERT_REG_POSITION(reduce_color_thresholds_fp16, 0x10EC);
+ASSERT_REG_POSITION(reduce_color_thresholds_srgb8, 0x10F0);
+ASSERT_REG_POSITION(unbind_all_constant_buffers, 0x10F4);
+ASSERT_REG_POSITION(clear_control, 0x10F8);
+ASSERT_REG_POSITION(l2_cache_rop_non_interlocked_reads, 0x10FC);
+ASSERT_REG_POSITION(reserved_sw_method14, 0x1100);
+ASSERT_REG_POSITION(reserved_sw_method15, 0x1104);
+ASSERT_REG_POSITION(no_operation_data_high, 0x110C);
+ASSERT_REG_POSITION(depth_bias_control, 0x1110);
+ASSERT_REG_POSITION(pm_trigger_end, 0x1114);
+ASSERT_REG_POSITION(vertex_id_base, 0x1118);
+ASSERT_REG_POSITION(stencil_compression_enabled, 0x111C);
+ASSERT_REG_POSITION(vertex_output_attribute_skip_masks, 0x1120);
+ASSERT_REG_POSITION(tir_control, 0x1130);
+ASSERT_REG_POSITION(mutable_method_treat_mutable_as_heavy, 0x1134);
+ASSERT_REG_POSITION(post_ps_use_pre_ps_coverage, 0x1138);
+ASSERT_REG_POSITION(fill_via_triangle_mode, 0x113C);
+ASSERT_REG_POSITION(blend_per_format_snorm8_unorm16_snorm16_enabled, 0x1140);
+ASSERT_REG_POSITION(flush_pending_writes_sm_gloal_store, 0x1144);
+ASSERT_REG_POSITION(vertex_attrib_format, 0x1160);
+ASSERT_REG_POSITION(multisample_sample_locations, 0x11E0);
+ASSERT_REG_POSITION(offset_render_target_index_by_viewport_index, 0x11F0);
+ASSERT_REG_POSITION(force_heavy_method_sync, 0x11F4);
+ASSERT_REG_POSITION(multisample_coverage_to_color, 0x11F8);
+ASSERT_REG_POSITION(decompress_zeta_surface, 0x11FC);
+ASSERT_REG_POSITION(zeta_sparse, 0x1208);
+ASSERT_REG_POSITION(invalidate_sampler_cache, 0x120C);
+ASSERT_REG_POSITION(invalidate_texture_header_cache, 0x1210);
+ASSERT_REG_POSITION(vertex_array_instance_first, 0x1214);
+ASSERT_REG_POSITION(vertex_array_instance_subsequent, 0x1218);
+ASSERT_REG_POSITION(rt_control, 0x121C);
+ASSERT_REG_POSITION(compression_threshold_samples, 0x1220);
+ASSERT_REG_POSITION(ps_interlock_control, 0x1224);
+ASSERT_REG_POSITION(zeta_size, 0x1228);
+ASSERT_REG_POSITION(sampler_binding, 0x1234);
+ASSERT_REG_POSITION(draw_auto_byte_count, 0x123C);
+ASSERT_REG_POSITION(post_vtg_shader_attrib_skip_mask, 0x1240);
+ASSERT_REG_POSITION(ps_ticket_dispenser_value, 0x1260);
+ASSERT_REG_POSITION(circular_buffer_size, 0x1280);
+ASSERT_REG_POSITION(vtg_register_watermarks, 0x1284);
+ASSERT_REG_POSITION(invalidate_texture_cache_no_wfi, 0x1288);
+ASSERT_REG_POSITION(l2_cache_rop_interlocked_reads, 0x1290);
+ASSERT_REG_POSITION(primitive_restart_topology_change_index, 0x12A4);
+ASSERT_REG_POSITION(zcull_region_enable, 0x12C8);
+ASSERT_REG_POSITION(depth_test_enable, 0x12CC);
+ASSERT_REG_POSITION(fill_mode, 0x12D0);
+ASSERT_REG_POSITION(shade_mode, 0x12D4);
+ASSERT_REG_POSITION(l2_cache_rop_non_interlocked_writes, 0x12D8);
+ASSERT_REG_POSITION(l2_cache_rop_interlocked_writes, 0x12DC);
+ASSERT_REG_POSITION(alpha_to_coverage_dither, 0x12E0);
+ASSERT_REG_POSITION(blend_per_target_enabled, 0x12E4);
+ASSERT_REG_POSITION(depth_write_enabled, 0x12E8);
+ASSERT_REG_POSITION(alpha_test_enabled, 0x12EC);
+ASSERT_REG_POSITION(inline_index_4x8_align, 0x1300);
+ASSERT_REG_POSITION(inline_index_4x8_index, 0x1304);
+ASSERT_REG_POSITION(d3d_cull_mode, 0x1308);
+ASSERT_REG_POSITION(depth_test_func, 0x130C);
+ASSERT_REG_POSITION(alpha_test_ref, 0x1310);
+ASSERT_REG_POSITION(alpha_test_func, 0x1314);
+ASSERT_REG_POSITION(draw_auto_stride, 0x1318);
+ASSERT_REG_POSITION(blend_color, 0x131C);
+ASSERT_REG_POSITION(invalidate_sampler_cache_lines, 0x1330);
+ASSERT_REG_POSITION(invalidate_texture_header_cache_lines, 0x1334);
+ASSERT_REG_POSITION(invalidate_texture_data_cache_lines, 0x1338);
+ASSERT_REG_POSITION(blend, 0x133C);
+ASSERT_REG_POSITION(stencil_enable, 0x1380);
+ASSERT_REG_POSITION(stencil_front_op, 0x1384);
+ASSERT_REG_POSITION(stencil_front_ref, 0x1394);
+ASSERT_REG_POSITION(stencil_front_func_mask, 0x1398);
+ASSERT_REG_POSITION(stencil_front_mask, 0x139C);
+ASSERT_REG_POSITION(draw_auto_start_byte_count, 0x13A4);
+ASSERT_REG_POSITION(frag_color_clamp, 0x13A8);
+ASSERT_REG_POSITION(window_origin, 0x13AC);
+ASSERT_REG_POSITION(line_width_smooth, 0x13B0);
+ASSERT_REG_POSITION(line_width_aliased, 0x13B4);
+ASSERT_REG_POSITION(line_override_multisample, 0x1418);
+ASSERT_REG_POSITION(alpha_hysteresis_rounds, 0x1420);
+ASSERT_REG_POSITION(invalidate_sampler_cache_no_wfi, 0x1424);
+ASSERT_REG_POSITION(invalidate_texture_header_cache_no_wfi, 0x1428);
+ASSERT_REG_POSITION(global_base_vertex_index, 0x1434);
+ASSERT_REG_POSITION(global_base_instance_index, 0x1438);
+ASSERT_REG_POSITION(ps_warp_watermarks, 0x1450);
+ASSERT_REG_POSITION(ps_regster_watermarks, 0x1454);
+ASSERT_REG_POSITION(store_zcull, 0x1464);
+ASSERT_REG_POSITION(iterated_blend_constants, 0x1480);
+ASSERT_REG_POSITION(load_zcull, 0x1500);
+ASSERT_REG_POSITION(surface_clip_id_height, 0x1504);
+ASSERT_REG_POSITION(surface_clip_id_clear_rect, 0x1508);
+ASSERT_REG_POSITION(user_clip_enable, 0x1510);
+ASSERT_REG_POSITION(zpass_pixel_count_enable, 0x1514);
+ASSERT_REG_POSITION(point_size, 0x1518);
+ASSERT_REG_POSITION(zcull_stats_enable, 0x151C);
+ASSERT_REG_POSITION(point_sprite_enable, 0x1520);
+ASSERT_REG_POSITION(shader_exceptions_enable, 0x1528);
+ASSERT_REG_POSITION(clear_report_value, 0x1530);
+ASSERT_REG_POSITION(anti_alias_enable, 0x1534);
+ASSERT_REG_POSITION(zeta_enable, 0x1538);
+ASSERT_REG_POSITION(anti_alias_alpha_control, 0x153C);
+ASSERT_REG_POSITION(render_enable, 0x1550);
+ASSERT_REG_POSITION(tex_sampler, 0x155C);
+ASSERT_REG_POSITION(slope_scale_depth_bias, 0x156C);
+ASSERT_REG_POSITION(line_anti_alias_enable, 0x1570);
+ASSERT_REG_POSITION(tex_header, 0x1574);
+ASSERT_REG_POSITION(active_zcull_region_id, 0x1590);
+ASSERT_REG_POSITION(stencil_two_side_enable, 0x1594);
+ASSERT_REG_POSITION(stencil_back_op, 0x1598);
+ASSERT_REG_POSITION(framebuffer_srgb, 0x15B8);
+ASSERT_REG_POSITION(depth_bias, 0x15BC);
+ASSERT_REG_POSITION(zcull_region_format, 0x15C8);
+ASSERT_REG_POSITION(rt_layer, 0x15CC);
+ASSERT_REG_POSITION(anti_alias_samples_mode, 0x15D0);
+ASSERT_REG_POSITION(edge_flag, 0x15E4);
+ASSERT_REG_POSITION(draw_inline_index, 0x15E8);
+ASSERT_REG_POSITION(inline_index_2x16, 0x15EC);
+ASSERT_REG_POSITION(vertex_global_base_offset, 0x15F4);
+ASSERT_REG_POSITION(zcull_region_pixel_offset, 0x15FC);
+ASSERT_REG_POSITION(point_sprite, 0x1604);
+ASSERT_REG_POSITION(program_region, 0x1608);
+ASSERT_REG_POSITION(default_attributes, 0x1610);
+ASSERT_REG_POSITION(draw, 0x1614);
+ASSERT_REG_POSITION(vertex_id_copy, 0x161C);
+ASSERT_REG_POSITION(add_to_primitive_id, 0x1620);
+ASSERT_REG_POSITION(load_to_primitive_id, 0x1624);
+ASSERT_REG_POSITION(shader_based_cull, 0x162C);
+ASSERT_REG_POSITION(class_version, 0x1638);
+ASSERT_REG_POSITION(primitive_restart, 0x1644);
+ASSERT_REG_POSITION(output_vertex_id, 0x164C);
+ASSERT_REG_POSITION(anti_alias_point_enable, 0x1658);
+ASSERT_REG_POSITION(point_center_mode, 0x165C);
+ASSERT_REG_POSITION(line_smooth_params, 0x1668);
+ASSERT_REG_POSITION(line_stipple_enable, 0x166C);
+ASSERT_REG_POSITION(line_smooth_edge_table, 0x1670);
+ASSERT_REG_POSITION(line_stipple_params, 0x1680);
+ASSERT_REG_POSITION(provoking_vertex, 0x1684);
+ASSERT_REG_POSITION(two_sided_light_enabled, 0x1688);
+ASSERT_REG_POSITION(polygon_stipple_enabled, 0x168C);
+ASSERT_REG_POSITION(shader_control, 0x1690);
+ASSERT_REG_POSITION(class_version_check, 0x16A0);
+ASSERT_REG_POSITION(sph_version, 0x16A4);
+ASSERT_REG_POSITION(sph_version_check, 0x16A8);
+ASSERT_REG_POSITION(alpha_to_coverage_override, 0x16B4);
+ASSERT_REG_POSITION(polygon_stipple_pattern, 0x1700);
+ASSERT_REG_POSITION(aam_version, 0x1790);
+ASSERT_REG_POSITION(aam_version_check, 0x1794);
+ASSERT_REG_POSITION(zeta_layer_offset, 0x179C);
+ASSERT_REG_POSITION(index_buffer, 0x17C8);
+ASSERT_REG_POSITION(index_buffer32_first, 0x17E4);
+ASSERT_REG_POSITION(index_buffer16_first, 0x17E8);
+ASSERT_REG_POSITION(index_buffer8_first, 0x17EC);
+ASSERT_REG_POSITION(index_buffer32_subsequent, 0x17F0);
+ASSERT_REG_POSITION(index_buffer16_subsequent, 0x17F4);
+ASSERT_REG_POSITION(index_buffer8_subsequent, 0x17F8);
+ASSERT_REG_POSITION(depth_bias_clamp, 0x187C);
+ASSERT_REG_POSITION(vertex_stream_instances, 0x1880);
+ASSERT_REG_POSITION(point_size_attribute, 0x1910);
+ASSERT_REG_POSITION(gl_cull_test_enabled, 0x1918);
+ASSERT_REG_POSITION(gl_front_face, 0x191C);
+ASSERT_REG_POSITION(gl_cull_face, 0x1920);
+ASSERT_REG_POSITION(viewport_pixel_center, 0x1924);
+ASSERT_REG_POSITION(viewport_scale_offset_enbled, 0x192C);
+ASSERT_REG_POSITION(viewport_clip_control, 0x193C);
+ASSERT_REG_POSITION(user_clip_op, 0x1940);
+ASSERT_REG_POSITION(render_enable_override, 0x1944);
+ASSERT_REG_POSITION(primitive_topology_control, 0x1948);
+ASSERT_REG_POSITION(window_clip_enable, 0x194C);
+ASSERT_REG_POSITION(invalidate_zcull, 0x1958);
+ASSERT_REG_POSITION(zcull, 0x1968);
+ASSERT_REG_POSITION(topology_override, 0x1970);
+ASSERT_REG_POSITION(zcull_sync, 0x1978);
+ASSERT_REG_POSITION(clip_id_test_enable, 0x197C);
+ASSERT_REG_POSITION(surface_clip_id_width, 0x1980);
+ASSERT_REG_POSITION(clip_id, 0x1984);
+ASSERT_REG_POSITION(depth_bounds_enable, 0x19BC);
+ASSERT_REG_POSITION(blend_float_zero_times_anything_is_zero, 0x19C0);
+ASSERT_REG_POSITION(logic_op, 0x19C4);
+ASSERT_REG_POSITION(z_compression_enable, 0x19CC);
+ASSERT_REG_POSITION(clear_surface, 0x19D0);
+ASSERT_REG_POSITION(clear_clip_id_surface, 0x19D4);
+ASSERT_REG_POSITION(color_compression_enable, 0x19E0);
+ASSERT_REG_POSITION(color_mask, 0x1A00);
+ASSERT_REG_POSITION(pipe_nop, 0x1A2C);
+ASSERT_REG_POSITION(spare, 0x1A30);
+ASSERT_REG_POSITION(report_semaphore, 0x1B00);
+ASSERT_REG_POSITION(vertex_streams, 0x1C00);
+ASSERT_REG_POSITION(blend_per_target, 0x1E00);
+ASSERT_REG_POSITION(vertex_stream_limits, 0x1F00);
+ASSERT_REG_POSITION(pipelines, 0x2000);
+ASSERT_REG_POSITION(falcon, 0x2300);
+ASSERT_REG_POSITION(const_buffer, 0x2380);
+ASSERT_REG_POSITION(bind_groups, 0x2400);
+ASSERT_REG_POSITION(color_clamp_enable, 0x2600);
+ASSERT_REG_POSITION(bindless_texture_const_buffer_slot, 0x2608);
+ASSERT_REG_POSITION(trap_handler, 0x260C);
+ASSERT_REG_POSITION(stream_out_layout, 0x2800);
+ASSERT_REG_POSITION(shader_performance, 0x333C);
+ASSERT_REG_POSITION(shadow_scratch, 0x3400);
#undef ASSERT_REG_POSITION
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index 0a4a8b14f..d0709dc69 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -24,11 +24,15 @@ namespace Tegra {
class DmaPusher;
struct CommandList;
+// TODO: Implement the commented ones
enum class RenderTargetFormat : u32 {
NONE = 0x0,
R32B32G32A32_FLOAT = 0xC0,
R32G32B32A32_SINT = 0xC1,
R32G32B32A32_UINT = 0xC2,
+ // R32G32B32X32_FLOAT = 0xC3,
+ // R32G32B32X32_SINT = 0xC4,
+ // R32G32B32X32_UINT = 0xC5,
R16G16B16A16_UNORM = 0xC6,
R16G16B16A16_SNORM = 0xC7,
R16G16B16A16_SINT = 0xC8,
@@ -38,8 +42,8 @@ enum class RenderTargetFormat : u32 {
R32G32_SINT = 0xCC,
R32G32_UINT = 0xCD,
R16G16B16X16_FLOAT = 0xCE,
- B8G8R8A8_UNORM = 0xCF,
- B8G8R8A8_SRGB = 0xD0,
+ A8R8G8B8_UNORM = 0xCF,
+ A8R8G8B8_SRGB = 0xD0,
A2B10G10R10_UNORM = 0xD1,
A2B10G10R10_UINT = 0xD2,
A8B8G8R8_UNORM = 0xD5,
@@ -52,10 +56,13 @@ enum class RenderTargetFormat : u32 {
R16G16_SINT = 0xDC,
R16G16_UINT = 0xDD,
R16G16_FLOAT = 0xDE,
+ // A2R10G10B10_UNORM = 0xDF,
B10G11R11_FLOAT = 0xE0,
R32_SINT = 0xE3,
R32_UINT = 0xE4,
R32_FLOAT = 0xE5,
+ // X8R8G8B8_UNORM = 0xE6,
+ // X8R8G8B8_SRGB = 0xE7,
R5G6B5_UNORM = 0xE8,
A1R5G5B5_UNORM = 0xE9,
R8G8_UNORM = 0xEA,
@@ -71,17 +78,42 @@ enum class RenderTargetFormat : u32 {
R8_SNORM = 0xF4,
R8_SINT = 0xF5,
R8_UINT = 0xF6,
+
+ /*
+ A8_UNORM = 0xF7,
+ X1R5G5B5_UNORM = 0xF8,
+ X8B8G8R8_UNORM = 0xF9,
+ X8B8G8R8_SRGB = 0xFA,
+ Z1R5G5B5_UNORM = 0xFB,
+ O1R5G5B5_UNORM = 0xFC,
+ Z8R8G8B8_UNORM = 0xFD,
+ O8R8G8B8_UNORM = 0xFE,
+ R32_UNORM = 0xFF,
+ A16_UNORM = 0x40,
+ A16_FLOAT = 0x41,
+ A32_FLOAT = 0x42,
+ A8R8_UNORM = 0x43,
+ R16A16_UNORM = 0x44,
+ R16A16_FLOAT = 0x45,
+ R32A32_FLOAT = 0x46,
+ B8G8R8A8_UNORM = 0x47,
+ */
};
enum class DepthFormat : u32 {
- D32_FLOAT = 0xA,
- D16_UNORM = 0x13,
- S8_UINT_Z24_UNORM = 0x14,
- D24X8_UNORM = 0x15,
- D24S8_UNORM = 0x16,
+ Z32_FLOAT = 0xA,
+ Z16_UNORM = 0x13,
+ Z24_UNORM_S8_UINT = 0x14,
+ X8Z24_UNORM = 0x15,
+ S8Z24_UNORM = 0x16,
S8_UINT = 0x17,
- D24C8_UNORM = 0x18,
- D32_FLOAT_S8X24_UINT = 0x19,
+ V8Z24_UNORM = 0x18,
+ Z32_FLOAT_X24S8_UINT = 0x19,
+ /*
+ X8Z24_UNORM_X16V8S8_UINT = 0x1D,
+ Z32_FLOAT_X16V8X8_UINT = 0x1E,
+ Z32_FLOAT_X16V8S8_UINT = 0x1F,
+ */
};
namespace Engines {
diff --git a/src/video_core/host1x/syncpoint_manager.cpp b/src/video_core/host1x/syncpoint_manager.cpp
index 326e8355a..a44fc83d3 100644
--- a/src/video_core/host1x/syncpoint_manager.cpp
+++ b/src/video_core/host1x/syncpoint_manager.cpp
@@ -36,7 +36,17 @@ SyncpointManager::ActionHandle SyncpointManager::RegisterAction(
void SyncpointManager::DeregisterAction(std::list<RegisteredAction>& action_storage,
ActionHandle& handle) {
std::unique_lock lk(guard);
- action_storage.erase(handle);
+
+ // We want to ensure the iterator still exists prior to erasing it
+ // Otherwise, if an invalid iterator was passed in then it could lead to UB
+ // It is important to avoid UB in that case since the deregister isn't called from a locked
+ // context
+ for (auto it = action_storage.begin(); it != action_storage.end(); it++) {
+ if (it == handle) {
+ action_storage.erase(it);
+ return;
+ }
+ }
}
void SyncpointManager::DeregisterGuestAction(u32 syncpoint_id, ActionHandle& handle) {
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp
index cabe8dcbf..8a8adbb42 100644
--- a/src/video_core/macro/macro_hle.cpp
+++ b/src/video_core/macro/macro_hle.cpp
@@ -21,16 +21,16 @@ void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
maxwell3d.regs.draw.topology.Assign(
static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0x3ffffff));
- maxwell3d.regs.vb_base_instance = parameters[5];
+ maxwell3d.regs.global_base_instance_index = parameters[5];
maxwell3d.mme_draw.instance_count = instance_count;
- maxwell3d.regs.vb_element_base = parameters[3];
- maxwell3d.regs.index_array.count = parameters[1];
- maxwell3d.regs.index_array.first = parameters[4];
+ maxwell3d.regs.global_base_vertex_index = parameters[3];
+ maxwell3d.regs.index_buffer.count = parameters[1];
+ maxwell3d.regs.index_buffer.first = parameters[4];
if (maxwell3d.ShouldExecute()) {
maxwell3d.Rasterizer().Draw(true, true);
}
- maxwell3d.regs.index_array.count = 0;
+ maxwell3d.regs.index_buffer.count = 0;
maxwell3d.mme_draw.instance_count = 0;
maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
}
@@ -40,7 +40,7 @@ void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
maxwell3d.regs.vertex_buffer.first = parameters[3];
maxwell3d.regs.vertex_buffer.count = parameters[1];
- maxwell3d.regs.vb_base_instance = parameters[4];
+ maxwell3d.regs.global_base_instance_index = parameters[4];
maxwell3d.regs.draw.topology.Assign(
static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]));
maxwell3d.mme_draw.instance_count = count;
@@ -57,12 +57,12 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]);
const u32 element_base = parameters[4];
const u32 base_instance = parameters[5];
- maxwell3d.regs.index_array.first = parameters[3];
- maxwell3d.regs.reg_array[0x446] = element_base; // vertex id base?
- maxwell3d.regs.index_array.count = parameters[1];
+ maxwell3d.regs.index_buffer.first = parameters[3];
+ maxwell3d.regs.vertex_id_base = element_base;
+ maxwell3d.regs.index_buffer.count = parameters[1];
maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
- maxwell3d.regs.vb_element_base = element_base;
- maxwell3d.regs.vb_base_instance = base_instance;
+ maxwell3d.regs.global_base_vertex_index = element_base;
+ maxwell3d.regs.global_base_instance_index = base_instance;
maxwell3d.mme_draw.instance_count = instance_count;
maxwell3d.CallMethodFromMME(0x8e3, 0x640);
maxwell3d.CallMethodFromMME(0x8e4, element_base);
@@ -72,10 +72,10 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
if (maxwell3d.ShouldExecute()) {
maxwell3d.Rasterizer().Draw(true, true);
}
- maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base?
- maxwell3d.regs.index_array.count = 0;
- maxwell3d.regs.vb_element_base = 0x0;
- maxwell3d.regs.vb_base_instance = 0x0;
+ maxwell3d.regs.vertex_id_base = 0x0;
+ maxwell3d.regs.index_buffer.count = 0;
+ maxwell3d.regs.global_base_vertex_index = 0x0;
+ maxwell3d.regs.global_base_instance_index = 0x0;
maxwell3d.mme_draw.instance_count = 0;
maxwell3d.CallMethodFromMME(0x8e3, 0x640);
maxwell3d.CallMethodFromMME(0x8e4, 0x0);
@@ -87,10 +87,10 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) {
SCOPE_EXIT({
// Clean everything.
- maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base?
- maxwell3d.regs.index_array.count = 0;
- maxwell3d.regs.vb_element_base = 0x0;
- maxwell3d.regs.vb_base_instance = 0x0;
+ maxwell3d.regs.vertex_id_base = 0x0;
+ maxwell3d.regs.index_buffer.count = 0;
+ maxwell3d.regs.global_base_vertex_index = 0x0;
+ maxwell3d.regs.global_base_instance_index = 0x0;
maxwell3d.mme_draw.instance_count = 0;
maxwell3d.CallMethodFromMME(0x8e3, 0x640);
maxwell3d.CallMethodFromMME(0x8e4, 0x0);
@@ -122,11 +122,11 @@ void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
const u32 first_index = parameters[base + 2];
const u32 base_vertex = parameters[base + 3];
const u32 base_instance = parameters[base + 4];
- maxwell3d.regs.index_array.first = first_index;
- maxwell3d.regs.reg_array[0x446] = base_vertex;
- maxwell3d.regs.index_array.count = num_vertices;
- maxwell3d.regs.vb_element_base = base_vertex;
- maxwell3d.regs.vb_base_instance = base_instance;
+ maxwell3d.regs.index_buffer.first = first_index;
+ maxwell3d.regs.vertex_id_base = base_vertex;
+ maxwell3d.regs.index_buffer.count = num_vertices;
+ maxwell3d.regs.global_base_vertex_index = base_vertex;
+ maxwell3d.regs.global_base_instance_index = base_instance;
maxwell3d.mme_draw.instance_count = instance_count;
maxwell3d.CallMethodFromMME(0x8e3, 0x640);
maxwell3d.CallMethodFromMME(0x8e4, base_vertex);
diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h
index b0ebe71b7..00ce53e3e 100644
--- a/src/video_core/query_cache.h
+++ b/src/video_core/query_cache.h
@@ -137,7 +137,7 @@ public:
std::unique_lock lock{mutex};
if (maxwell3d) {
const auto& regs = maxwell3d->regs;
- Stream(VideoCore::QueryType::SamplesPassed).Update(regs.samplecnt_enable);
+ Stream(VideoCore::QueryType::SamplesPassed).Update(regs.zpass_pixel_count_enable);
}
}
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp
index 45791aa75..e8761a747 100644
--- a/src/video_core/renderer_base.cpp
+++ b/src/video_core/renderer_base.cpp
@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include <thread>
+
#include "common/logging/log.h"
#include "core/frontend/emu_window.h"
#include "video_core/renderer_base.h"
@@ -35,8 +37,12 @@ void RendererBase::RequestScreenshot(void* data, std::function<void(bool)> callb
LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request");
return;
}
+ auto async_callback{[callback = std::move(callback)](bool invert_y) {
+ std::thread t{callback, invert_y};
+ t.detach();
+ }};
renderer_settings.screenshot_bits = data;
- renderer_settings.screenshot_complete_callback = std::move(callback);
+ renderer_settings.screenshot_complete_callback = async_callback;
renderer_settings.screenshot_framebuffer_layout = layout;
renderer_settings.screenshot_requested = true;
}
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
index 41493a7da..1d20a79ec 100644
--- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
@@ -73,8 +73,8 @@ GLenum AssemblyStage(size_t stage_index) {
/// @param location Hardware location
/// @return Pair of ARB_transform_feedback3 token stream first and third arguments
/// @note Read https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_transform_feedback3.txt
-std::pair<GLint, GLint> TransformFeedbackEnum(u8 location) {
- const u8 index = location / 4;
+std::pair<GLint, GLint> TransformFeedbackEnum(u32 location) {
+ const auto index = location / 4;
if (index >= 8 && index <= 39) {
return {GL_GENERIC_ATTRIB_NV, index - 8};
}
@@ -286,7 +286,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
buffer_cache.runtime.SetEnableStorageBuffers(use_storage_buffers);
const auto& regs{maxwell3d->regs};
- const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex};
+ const bool via_header_index{regs.sampler_binding == Maxwell::SamplerBinding::ViaHeaderBinding};
const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
const Shader::Info& info{stage_infos[stage]};
buffer_cache.UnbindGraphicsStorageBuffers(stage);
@@ -557,10 +557,25 @@ void GraphicsPipeline::GenerateTransformFeedbackState() {
++current_stream;
const auto& locations = key.xfb_state.varyings[feedback];
- std::optional<u8> current_index;
+ std::optional<u32> current_index;
for (u32 offset = 0; offset < layout.varying_count; ++offset) {
- const u8 location = locations[offset];
- const u8 index = location / 4;
+ const auto get_attribute = [&locations](u32 index) -> u32 {
+ switch (index % 4) {
+ case 0:
+ return locations[index / 4].attribute0.Value();
+ case 1:
+ return locations[index / 4].attribute1.Value();
+ case 2:
+ return locations[index / 4].attribute2.Value();
+ case 3:
+ return locations[index / 4].attribute3.Value();
+ }
+ UNREACHABLE();
+ return 0;
+ };
+
+ const auto attribute{get_attribute(offset)};
+ const auto index = attribute / 4U;
if (current_index == index) {
// Increase number of components of the previous attachment
@@ -569,7 +584,7 @@ void GraphicsPipeline::GenerateTransformFeedbackState() {
}
current_index = index;
- std::tie(cursor[0], cursor[2]) = TransformFeedbackEnum(location);
+ std::tie(cursor[0], cursor[2]) = TransformFeedbackEnum(attribute);
cursor[1] = 1;
cursor += XFB_ENTRY_STRIDE;
}
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.h b/src/video_core/renderer_opengl/gl_graphics_pipeline.h
index a0f0e63cb..ea53ddb46 100644
--- a/src/video_core/renderer_opengl/gl_graphics_pipeline.h
+++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.h
@@ -37,8 +37,8 @@ struct GraphicsPipelineKey {
BitField<0, 1, u32> xfb_enabled;
BitField<1, 1, u32> early_z;
BitField<2, 4, Maxwell::PrimitiveTopology> gs_input_topology;
- BitField<6, 2, Maxwell::TessellationPrimitive> tessellation_primitive;
- BitField<8, 2, Maxwell::TessellationSpacing> tessellation_spacing;
+ BitField<6, 2, Maxwell::Tessellation::DomainType> tessellation_primitive;
+ BitField<8, 2, Maxwell::Tessellation::Spacing> tessellation_spacing;
BitField<10, 1, u32> tessellation_clockwise;
};
std::array<u32, 3> padding;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index c2d80605d..e5c09a969 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -87,7 +87,7 @@ void RasterizerOpenGL::SyncVertexFormats() {
}
flags[Dirty::VertexFormat0 + index] = false;
- const auto attrib = maxwell3d->regs.vertex_attrib_format[index];
+ const auto& attrib = maxwell3d->regs.vertex_attrib_format[index];
const auto gl_index = static_cast<GLuint>(index);
// Disable constant attributes.
@@ -97,8 +97,8 @@ void RasterizerOpenGL::SyncVertexFormats() {
}
glEnableVertexAttribArray(gl_index);
- if (attrib.type == Maxwell::VertexAttribute::Type::SignedInt ||
- attrib.type == Maxwell::VertexAttribute::Type::UnsignedInt) {
+ if (attrib.type == Maxwell::VertexAttribute::Type::SInt ||
+ attrib.type == Maxwell::VertexAttribute::Type::UInt) {
glVertexAttribIFormat(gl_index, attrib.ComponentCount(),
MaxwellToGL::VertexFormat(attrib), attrib.offset);
} else {
@@ -125,8 +125,8 @@ void RasterizerOpenGL::SyncVertexInstances() {
flags[Dirty::VertexInstance0 + index] = false;
const auto gl_index = static_cast<GLuint>(index);
- const bool instancing_enabled = regs.instanced_arrays.IsInstancingEnabled(gl_index);
- const GLuint divisor = instancing_enabled ? regs.vertex_array[index].divisor : 0;
+ const bool instancing_enabled = regs.vertex_stream_instances.IsInstancingEnabled(gl_index);
+ const GLuint divisor = instancing_enabled ? regs.vertex_streams[index].frequency : 0;
glVertexBindingDivisor(gl_index, divisor);
}
}
@@ -147,27 +147,27 @@ void RasterizerOpenGL::Clear() {
bool use_depth{};
bool use_stencil{};
- if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
- regs.clear_buffers.A) {
+ if (regs.clear_surface.R || regs.clear_surface.G || regs.clear_surface.B ||
+ regs.clear_surface.A) {
use_color = true;
- const GLuint index = regs.clear_buffers.RT;
+ const GLuint index = regs.clear_surface.RT;
state_tracker.NotifyColorMask(index);
- glColorMaski(index, regs.clear_buffers.R != 0, regs.clear_buffers.G != 0,
- regs.clear_buffers.B != 0, regs.clear_buffers.A != 0);
+ glColorMaski(index, regs.clear_surface.R != 0, regs.clear_surface.G != 0,
+ regs.clear_surface.B != 0, regs.clear_surface.A != 0);
// TODO(Rodrigo): Determine if clamping is used on clears
SyncFragmentColorClampState();
SyncFramebufferSRGB();
}
- if (regs.clear_buffers.Z) {
+ if (regs.clear_surface.Z) {
ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear Z but buffer is not enabled!");
use_depth = true;
state_tracker.NotifyDepthMask();
glDepthMask(GL_TRUE);
}
- if (regs.clear_buffers.S) {
+ if (regs.clear_surface.S) {
ASSERT_MSG(regs.zeta_enable, "Tried to clear stencil but buffer is not enabled!");
use_stencil = true;
}
@@ -184,16 +184,16 @@ void RasterizerOpenGL::Clear() {
texture_cache.UpdateRenderTargets(true);
state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle());
SyncViewport();
- if (regs.clear_flags.scissor) {
+ if (regs.clear_control.use_scissor) {
SyncScissorTest();
} else {
state_tracker.NotifyScissor0();
glDisablei(GL_SCISSOR_TEST, 0);
}
- UNIMPLEMENTED_IF(regs.clear_flags.viewport);
+ UNIMPLEMENTED_IF(regs.clear_control.use_viewport_clip0);
if (use_color) {
- glClearBufferfv(GL_COLOR, regs.clear_buffers.RT, regs.clear_color);
+ glClearBufferfv(GL_COLOR, regs.clear_surface.RT, regs.clear_color.data());
}
if (use_depth && use_stencil) {
glClearBufferfi(GL_DEPTH_STENCIL, 0, regs.clear_depth, regs.clear_stencil);
@@ -227,14 +227,14 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(maxwell3d->regs.draw.topology);
BeginTransformFeedback(pipeline, primitive_mode);
- const GLuint base_instance = static_cast<GLuint>(maxwell3d->regs.vb_base_instance);
+ const GLuint base_instance = static_cast<GLuint>(maxwell3d->regs.global_base_instance_index);
const GLsizei num_instances =
static_cast<GLsizei>(is_instanced ? maxwell3d->mme_draw.instance_count : 1);
if (is_indexed) {
- const GLint base_vertex = static_cast<GLint>(maxwell3d->regs.vb_element_base);
- const GLsizei num_vertices = static_cast<GLsizei>(maxwell3d->regs.index_array.count);
+ const GLint base_vertex = static_cast<GLint>(maxwell3d->regs.global_base_vertex_index);
+ const GLsizei num_vertices = static_cast<GLsizei>(maxwell3d->regs.index_buffer.count);
const GLvoid* const offset = buffer_cache_runtime.IndexOffset();
- const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_array.format);
+ const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format);
if (num_instances == 1 && base_instance == 0 && base_vertex == 0) {
glDrawElements(primitive_mode, num_vertices, format, offset);
} else if (num_instances == 1 && base_instance == 0) {
@@ -555,9 +555,9 @@ void RasterizerOpenGL::SyncViewport() {
if (dirty_viewport || dirty_clip_control || flags[Dirty::FrontFace]) {
flags[Dirty::FrontFace] = false;
- GLenum mode = MaxwellToGL::FrontFace(regs.front_face);
+ GLenum mode = MaxwellToGL::FrontFace(regs.gl_front_face);
bool flip_faces = true;
- if (regs.screen_y_control.triangle_rast_flip != 0) {
+ if (regs.window_origin.flip_y != 0) {
flip_faces = !flip_faces;
}
if (regs.viewport_transform[0].scale_y < 0.0f) {
@@ -582,14 +582,15 @@ void RasterizerOpenGL::SyncViewport() {
if (regs.viewport_transform[0].scale_y < 0.0f) {
flip_y = !flip_y;
}
- if (regs.screen_y_control.y_negate != 0) {
+ const bool lower_left{regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft};
+ if (lower_left) {
flip_y = !flip_y;
}
const bool is_zero_to_one = regs.depth_mode == Maxwell::DepthMode::ZeroToOne;
const GLenum origin = flip_y ? GL_UPPER_LEFT : GL_LOWER_LEFT;
const GLenum depth = is_zero_to_one ? GL_ZERO_TO_ONE : GL_NEGATIVE_ONE_TO_ONE;
state_tracker.ClipControl(origin, depth);
- state_tracker.SetYNegate(regs.screen_y_control.y_negate != 0);
+ state_tracker.SetYNegate(lower_left);
}
const bool is_rescaling{texture_cache.IsRescaling()};
const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f;
@@ -657,7 +658,13 @@ void RasterizerOpenGL::SyncDepthClamp() {
}
flags[Dirty::DepthClampEnabled] = false;
- oglEnable(GL_DEPTH_CLAMP, maxwell3d->regs.view_volume_clip_control.depth_clamp_disabled == 0);
+ bool depth_clamp_disabled{maxwell3d->regs.viewport_clip_control.geometry_clip ==
+ Maxwell::ViewportClipControl::GeometryClip::Passthrough ||
+ maxwell3d->regs.viewport_clip_control.geometry_clip ==
+ Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ ||
+ maxwell3d->regs.viewport_clip_control.geometry_clip ==
+ Maxwell::ViewportClipControl::GeometryClip::FrustumZ};
+ oglEnable(GL_DEPTH_CLAMP, !depth_clamp_disabled);
}
void RasterizerOpenGL::SyncClipEnabled(u32 clip_mask) {
@@ -667,7 +674,7 @@ void RasterizerOpenGL::SyncClipEnabled(u32 clip_mask) {
}
flags[Dirty::ClipDistances] = false;
- clip_mask &= maxwell3d->regs.clip_distance_enabled;
+ clip_mask &= maxwell3d->regs.user_clip_enable.raw;
if (clip_mask == last_clip_distance_mask) {
return;
}
@@ -689,9 +696,9 @@ void RasterizerOpenGL::SyncCullMode() {
if (flags[Dirty::CullTest]) {
flags[Dirty::CullTest] = false;
- if (regs.cull_test_enabled) {
+ if (regs.gl_cull_test_enabled) {
glEnable(GL_CULL_FACE);
- glCullFace(MaxwellToGL::CullFace(regs.cull_face));
+ glCullFace(MaxwellToGL::CullFace(regs.gl_cull_face));
} else {
glDisable(GL_CULL_FACE);
}
@@ -743,19 +750,19 @@ void RasterizerOpenGL::SyncStencilTestState() {
const auto& regs = maxwell3d->regs;
oglEnable(GL_STENCIL_TEST, regs.stencil_enable);
- glStencilFuncSeparate(GL_FRONT, MaxwellToGL::ComparisonOp(regs.stencil_front_func_func),
- regs.stencil_front_func_ref, regs.stencil_front_func_mask);
- glStencilOpSeparate(GL_FRONT, MaxwellToGL::StencilOp(regs.stencil_front_op_fail),
- MaxwellToGL::StencilOp(regs.stencil_front_op_zfail),
- MaxwellToGL::StencilOp(regs.stencil_front_op_zpass));
+ glStencilFuncSeparate(GL_FRONT, MaxwellToGL::ComparisonOp(regs.stencil_front_op.func),
+ regs.stencil_front_ref, regs.stencil_front_func_mask);
+ glStencilOpSeparate(GL_FRONT, MaxwellToGL::StencilOp(regs.stencil_front_op.fail),
+ MaxwellToGL::StencilOp(regs.stencil_front_op.zfail),
+ MaxwellToGL::StencilOp(regs.stencil_front_op.zpass));
glStencilMaskSeparate(GL_FRONT, regs.stencil_front_mask);
if (regs.stencil_two_side_enable) {
- glStencilFuncSeparate(GL_BACK, MaxwellToGL::ComparisonOp(regs.stencil_back_func_func),
- regs.stencil_back_func_ref, regs.stencil_back_func_mask);
- glStencilOpSeparate(GL_BACK, MaxwellToGL::StencilOp(regs.stencil_back_op_fail),
- MaxwellToGL::StencilOp(regs.stencil_back_op_zfail),
- MaxwellToGL::StencilOp(regs.stencil_back_op_zpass));
+ glStencilFuncSeparate(GL_BACK, MaxwellToGL::ComparisonOp(regs.stencil_back_op.func),
+ regs.stencil_back_ref, regs.stencil_back_mask);
+ glStencilOpSeparate(GL_BACK, MaxwellToGL::StencilOp(regs.stencil_back_op.fail),
+ MaxwellToGL::StencilOp(regs.stencil_back_op.zfail),
+ MaxwellToGL::StencilOp(regs.stencil_back_op.zpass));
glStencilMaskSeparate(GL_BACK, regs.stencil_back_mask);
} else {
glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 0xFFFFFFFF);
@@ -782,7 +789,7 @@ void RasterizerOpenGL::SyncPolygonModes() {
flags[Dirty::PolygonModes] = false;
const auto& regs = maxwell3d->regs;
- if (regs.fill_rectangle) {
+ if (regs.fill_via_triangle_mode != Maxwell::FillViaTriangleMode::Disabled) {
if (!GLAD_GL_NV_fill_rectangle) {
LOG_ERROR(Render_OpenGL, "GL_NV_fill_rectangle used and not supported");
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
@@ -855,8 +862,8 @@ void RasterizerOpenGL::SyncMultiSampleState() {
flags[Dirty::MultisampleControl] = false;
const auto& regs = maxwell3d->regs;
- oglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE, regs.multisample_control.alpha_to_coverage);
- oglEnable(GL_SAMPLE_ALPHA_TO_ONE, regs.multisample_control.alpha_to_one);
+ oglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE, regs.anti_alias_alpha_control.alpha_to_coverage);
+ oglEnable(GL_SAMPLE_ALPHA_TO_ONE, regs.anti_alias_alpha_control.alpha_to_one);
}
void RasterizerOpenGL::SyncFragmentColorClampState() {
@@ -866,7 +873,8 @@ void RasterizerOpenGL::SyncFragmentColorClampState() {
}
flags[Dirty::FragmentClampColor] = false;
- glClampColor(GL_CLAMP_FRAGMENT_COLOR, maxwell3d->regs.frag_color_clamp ? GL_TRUE : GL_FALSE);
+ glClampColor(GL_CLAMP_FRAGMENT_COLOR,
+ maxwell3d->regs.frag_color_clamp.AnyEnabled() ? GL_TRUE : GL_FALSE);
}
void RasterizerOpenGL::SyncBlendState() {
@@ -886,18 +894,18 @@ void RasterizerOpenGL::SyncBlendState() {
}
flags[Dirty::BlendStates] = false;
- if (!regs.independent_blend_enable) {
+ if (!regs.blend_per_target_enabled) {
if (!regs.blend.enable[0]) {
glDisable(GL_BLEND);
return;
}
glEnable(GL_BLEND);
- glBlendFuncSeparate(MaxwellToGL::BlendFunc(regs.blend.factor_source_rgb),
- MaxwellToGL::BlendFunc(regs.blend.factor_dest_rgb),
- MaxwellToGL::BlendFunc(regs.blend.factor_source_a),
- MaxwellToGL::BlendFunc(regs.blend.factor_dest_a));
- glBlendEquationSeparate(MaxwellToGL::BlendEquation(regs.blend.equation_rgb),
- MaxwellToGL::BlendEquation(regs.blend.equation_a));
+ glBlendFuncSeparate(MaxwellToGL::BlendFunc(regs.blend.color_source),
+ MaxwellToGL::BlendFunc(regs.blend.color_dest),
+ MaxwellToGL::BlendFunc(regs.blend.alpha_source),
+ MaxwellToGL::BlendFunc(regs.blend.alpha_dest));
+ glBlendEquationSeparate(MaxwellToGL::BlendEquation(regs.blend.color_op),
+ MaxwellToGL::BlendEquation(regs.blend.alpha_op));
return;
}
@@ -916,14 +924,13 @@ void RasterizerOpenGL::SyncBlendState() {
}
glEnablei(GL_BLEND, static_cast<GLuint>(i));
- const auto& src = regs.independent_blend[i];
- glBlendFuncSeparatei(static_cast<GLuint>(i), MaxwellToGL::BlendFunc(src.factor_source_rgb),
- MaxwellToGL::BlendFunc(src.factor_dest_rgb),
- MaxwellToGL::BlendFunc(src.factor_source_a),
- MaxwellToGL::BlendFunc(src.factor_dest_a));
- glBlendEquationSeparatei(static_cast<GLuint>(i),
- MaxwellToGL::BlendEquation(src.equation_rgb),
- MaxwellToGL::BlendEquation(src.equation_a));
+ const auto& src = regs.blend_per_target[i];
+ glBlendFuncSeparatei(static_cast<GLuint>(i), MaxwellToGL::BlendFunc(src.color_source),
+ MaxwellToGL::BlendFunc(src.color_dest),
+ MaxwellToGL::BlendFunc(src.alpha_source),
+ MaxwellToGL::BlendFunc(src.alpha_dest));
+ glBlendEquationSeparatei(static_cast<GLuint>(i), MaxwellToGL::BlendEquation(src.color_op),
+ MaxwellToGL::BlendEquation(src.alpha_op));
}
}
@@ -937,7 +944,7 @@ void RasterizerOpenGL::SyncLogicOpState() {
const auto& regs = maxwell3d->regs;
if (regs.logic_op.enable) {
glEnable(GL_COLOR_LOGIC_OP);
- glLogicOp(MaxwellToGL::LogicOp(regs.logic_op.operation));
+ glLogicOp(MaxwellToGL::LogicOp(regs.logic_op.op));
} else {
glDisable(GL_COLOR_LOGIC_OP);
}
@@ -996,7 +1003,7 @@ void RasterizerOpenGL::SyncPointState() {
flags[Dirty::PointSize] = false;
oglEnable(GL_POINT_SPRITE, maxwell3d->regs.point_sprite_enable);
- oglEnable(GL_PROGRAM_POINT_SIZE, maxwell3d->regs.vp_point_size.enable);
+ oglEnable(GL_PROGRAM_POINT_SIZE, maxwell3d->regs.point_size_attribute.enabled);
const bool is_rescaling{texture_cache.IsRescaling()};
const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f;
glPointSize(std::max(1.0f, maxwell3d->regs.point_size * scale));
@@ -1010,8 +1017,8 @@ void RasterizerOpenGL::SyncLineState() {
flags[Dirty::LineWidth] = false;
const auto& regs = maxwell3d->regs;
- oglEnable(GL_LINE_SMOOTH, regs.line_smooth_enable);
- glLineWidth(regs.line_smooth_enable ? regs.line_width_smooth : regs.line_width_aliased);
+ oglEnable(GL_LINE_SMOOTH, regs.line_anti_alias_enable);
+ glLineWidth(regs.line_anti_alias_enable ? regs.line_width_smooth : regs.line_width_aliased);
}
void RasterizerOpenGL::SyncPolygonOffset() {
@@ -1029,8 +1036,8 @@ void RasterizerOpenGL::SyncPolygonOffset() {
if (regs.polygon_offset_fill_enable || regs.polygon_offset_line_enable ||
regs.polygon_offset_point_enable) {
// Hardware divides polygon offset units by two
- glPolygonOffsetClamp(regs.polygon_offset_factor, regs.polygon_offset_units / 2.0f,
- regs.polygon_offset_clamp);
+ glPolygonOffsetClamp(regs.slope_scale_depth_bias, regs.depth_bias / 2.0f,
+ regs.depth_bias_clamp);
}
}
@@ -1062,14 +1069,14 @@ void RasterizerOpenGL::SyncFramebufferSRGB() {
void RasterizerOpenGL::BeginTransformFeedback(GraphicsPipeline* program, GLenum primitive_mode) {
const auto& regs = maxwell3d->regs;
- if (regs.tfb_enabled == 0) {
+ if (regs.transform_feedback_enabled == 0) {
return;
}
program->ConfigureTransformFeedback();
- UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationControl) ||
- regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationEval) ||
- regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::Geometry));
+ UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderType::TessellationInit) ||
+ regs.IsShaderConfigEnabled(Maxwell::ShaderType::Tessellation) ||
+ regs.IsShaderConfigEnabled(Maxwell::ShaderType::Geometry));
UNIMPLEMENTED_IF(primitive_mode != GL_POINTS);
// We may have to call BeginTransformFeedbackNV here since they seem to call different
@@ -1080,7 +1087,7 @@ void RasterizerOpenGL::BeginTransformFeedback(GraphicsPipeline* program, GLenum
}
void RasterizerOpenGL::EndTransformFeedback() {
- if (maxwell3d->regs.tfb_enabled != 0) {
+ if (maxwell3d->regs.transform_feedback_enabled != 0) {
glEndTransformFeedback();
}
}
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 5a29a41d2..6bdb0b645 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -78,11 +78,11 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
info.tess_clockwise = key.tessellation_clockwise != 0;
info.tess_primitive = [&key] {
switch (key.tessellation_primitive) {
- case Maxwell::TessellationPrimitive::Isolines:
+ case Maxwell::Tessellation::DomainType::Isolines:
return Shader::TessPrimitive::Isolines;
- case Maxwell::TessellationPrimitive::Triangles:
+ case Maxwell::Tessellation::DomainType::Triangles:
return Shader::TessPrimitive::Triangles;
- case Maxwell::TessellationPrimitive::Quads:
+ case Maxwell::Tessellation::DomainType::Quads:
return Shader::TessPrimitive::Quads;
}
ASSERT(false);
@@ -90,11 +90,11 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
}();
info.tess_spacing = [&] {
switch (key.tessellation_spacing) {
- case Maxwell::TessellationSpacing::Equal:
+ case Maxwell::Tessellation::Spacing::Integer:
return Shader::TessSpacing::Equal;
- case Maxwell::TessellationSpacing::FractionalOdd:
+ case Maxwell::Tessellation::Spacing::FractionalOdd:
return Shader::TessSpacing::FractionalOdd;
- case Maxwell::TessellationSpacing::FractionalEven:
+ case Maxwell::Tessellation::Spacing::FractionalEven:
return Shader::TessSpacing::FractionalEven;
}
ASSERT(false);
@@ -139,14 +139,15 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
}
void SetXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs) {
- std::ranges::transform(regs.tfb_layouts, state.layouts.begin(), [](const auto& layout) {
- return VideoCommon::TransformFeedbackState::Layout{
- .stream = layout.stream,
- .varying_count = layout.varying_count,
- .stride = layout.stride,
- };
- });
- state.varyings = regs.tfb_varying_locs;
+ std::ranges::transform(regs.transform_feedback.controls, state.layouts.begin(),
+ [](const auto& layout) {
+ return VideoCommon::TransformFeedbackState::Layout{
+ .stream = layout.stream,
+ .varying_count = layout.varying_count,
+ .stride = layout.stride,
+ };
+ });
+ state.varyings = regs.stream_out_layout;
}
} // Anonymous namespace
@@ -309,14 +310,16 @@ GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() {
}
const auto& regs{maxwell3d->regs};
graphics_key.raw = 0;
- graphics_key.early_z.Assign(regs.force_early_fragment_tests != 0 ? 1 : 0);
+ graphics_key.early_z.Assign(regs.mandated_early_z != 0 ? 1 : 0);
graphics_key.gs_input_topology.Assign(graphics_key.unique_hashes[4] != 0
? regs.draw.topology.Value()
: Maxwell::PrimitiveTopology{});
- graphics_key.tessellation_primitive.Assign(regs.tess_mode.prim.Value());
- graphics_key.tessellation_spacing.Assign(regs.tess_mode.spacing.Value());
- graphics_key.tessellation_clockwise.Assign(regs.tess_mode.cw.Value());
- graphics_key.xfb_enabled.Assign(regs.tfb_enabled != 0 ? 1 : 0);
+ graphics_key.tessellation_primitive.Assign(regs.tessellation.params.domain_type.Value());
+ graphics_key.tessellation_spacing.Assign(regs.tessellation.params.spacing.Value());
+ graphics_key.tessellation_clockwise.Assign(
+ regs.tessellation.params.output_primitives.Value() !=
+ Maxwell::Tessellation::OutputPrimitves::Triangles_CCW);
+ graphics_key.xfb_enabled.Assign(regs.transform_feedback_enabled != 0 ? 1 : 0);
if (graphics_key.xfb_enabled) {
SetXfbState(graphics_key.xfb_state, regs);
}
@@ -354,7 +357,7 @@ GraphicsPipeline* ShaderCache::BuiltPipeline(GraphicsPipeline* pipeline) const n
// If games are using a small index count, we can assume these are full screen quads.
// Usually these shaders are only used once for building textures so we can assume they
// can't be built async
- if (maxwell3d->regs.index_array.count <= 6 || maxwell3d->regs.vertex_buffer.count <= 6) {
+ if (maxwell3d->regs.index_buffer.count <= 6 || maxwell3d->regs.vertex_buffer.count <= 6) {
return pipeline;
}
return nullptr;
diff --git a/src/video_core/renderer_opengl/gl_state_tracker.cpp b/src/video_core/renderer_opengl/gl_state_tracker.cpp
index a8f3a0f57..a359f96f1 100644
--- a/src/video_core/renderer_opengl/gl_state_tracker.cpp
+++ b/src/video_core/renderer_opengl/gl_state_tracker.cpp
@@ -38,12 +38,12 @@ void SetupDirtyColorMasks(Tables& tables) {
void SetupDirtyVertexInstances(Tables& tables) {
static constexpr std::size_t instance_base_offset = 3;
for (std::size_t i = 0; i < Regs::NumVertexArrays; ++i) {
- const std::size_t array_offset = OFF(vertex_array) + i * NUM(vertex_array[0]);
+ const std::size_t array_offset = OFF(vertex_streams) + i * NUM(vertex_streams[0]);
const std::size_t instance_array_offset = array_offset + instance_base_offset;
tables[0][instance_array_offset] = static_cast<u8>(VertexInstance0 + i);
tables[1][instance_array_offset] = VertexInstances;
- const std::size_t instance_offset = OFF(instanced_arrays) + i;
+ const std::size_t instance_offset = OFF(vertex_stream_instances) + i;
tables[0][instance_offset] = static_cast<u8>(VertexInstance0 + i);
tables[1][instance_offset] = VertexInstances;
}
@@ -70,8 +70,8 @@ void SetupDirtyViewports(Tables& tables) {
FillBlock(tables[1], OFF(viewport_transform), NUM(viewport_transform), Viewports);
FillBlock(tables[1], OFF(viewports), NUM(viewports), Viewports);
- tables[0][OFF(viewport_transform_enabled)] = ViewportTransform;
- tables[1][OFF(viewport_transform_enabled)] = Viewports;
+ tables[0][OFF(viewport_scale_offset_enbled)] = ViewportTransform;
+ tables[1][OFF(viewport_scale_offset_enbled)] = Viewports;
}
void SetupDirtyScissors(Tables& tables) {
@@ -88,7 +88,7 @@ void SetupDirtyPolygonModes(Tables& tables) {
tables[1][OFF(polygon_mode_front)] = PolygonModes;
tables[1][OFF(polygon_mode_back)] = PolygonModes;
- tables[0][OFF(fill_rectangle)] = PolygonModes;
+ tables[0][OFF(fill_via_triangle_mode)] = PolygonModes;
}
void SetupDirtyDepthTest(Tables& tables) {
@@ -100,11 +100,11 @@ void SetupDirtyDepthTest(Tables& tables) {
void SetupDirtyStencilTest(Tables& tables) {
static constexpr std::array offsets = {
- OFF(stencil_enable), OFF(stencil_front_func_func), OFF(stencil_front_func_ref),
- OFF(stencil_front_func_mask), OFF(stencil_front_op_fail), OFF(stencil_front_op_zfail),
- OFF(stencil_front_op_zpass), OFF(stencil_front_mask), OFF(stencil_two_side_enable),
- OFF(stencil_back_func_func), OFF(stencil_back_func_ref), OFF(stencil_back_func_mask),
- OFF(stencil_back_op_fail), OFF(stencil_back_op_zfail), OFF(stencil_back_op_zpass),
+ OFF(stencil_enable), OFF(stencil_front_op.func), OFF(stencil_front_ref),
+ OFF(stencil_front_func_mask), OFF(stencil_front_op.fail), OFF(stencil_front_op.zfail),
+ OFF(stencil_front_op.zpass), OFF(stencil_front_mask), OFF(stencil_two_side_enable),
+ OFF(stencil_back_op.func), OFF(stencil_back_ref), OFF(stencil_back_func_mask),
+ OFF(stencil_back_op.fail), OFF(stencil_back_op.zfail), OFF(stencil_back_op.zpass),
OFF(stencil_back_mask)};
for (const auto offset : offsets) {
tables[0][offset] = StencilTest;
@@ -121,15 +121,15 @@ void SetupDirtyAlphaTest(Tables& tables) {
void SetupDirtyBlend(Tables& tables) {
FillBlock(tables[0], OFF(blend_color), NUM(blend_color), BlendColor);
- tables[0][OFF(independent_blend_enable)] = BlendIndependentEnabled;
+ tables[0][OFF(blend_per_target_enabled)] = BlendIndependentEnabled;
for (std::size_t i = 0; i < Regs::NumRenderTargets; ++i) {
- const std::size_t offset = OFF(independent_blend) + i * NUM(independent_blend[0]);
- FillBlock(tables[0], offset, NUM(independent_blend[0]), BlendState0 + i);
+ const std::size_t offset = OFF(blend_per_target) + i * NUM(blend_per_target[0]);
+ FillBlock(tables[0], offset, NUM(blend_per_target[0]), BlendState0 + i);
tables[0][OFF(blend.enable) + i] = static_cast<u8>(BlendState0 + i);
}
- FillBlock(tables[1], OFF(independent_blend), NUM(independent_blend), BlendStates);
+ FillBlock(tables[1], OFF(blend_per_target), NUM(blend_per_target), BlendStates);
FillBlock(tables[1], OFF(blend), NUM(blend), BlendStates);
}
@@ -142,13 +142,14 @@ void SetupDirtyPolygonOffset(Tables& tables) {
table[OFF(polygon_offset_fill_enable)] = PolygonOffset;
table[OFF(polygon_offset_line_enable)] = PolygonOffset;
table[OFF(polygon_offset_point_enable)] = PolygonOffset;
- table[OFF(polygon_offset_factor)] = PolygonOffset;
- table[OFF(polygon_offset_units)] = PolygonOffset;
- table[OFF(polygon_offset_clamp)] = PolygonOffset;
+ table[OFF(slope_scale_depth_bias)] = PolygonOffset;
+ table[OFF(depth_bias)] = PolygonOffset;
+ table[OFF(depth_bias_clamp)] = PolygonOffset;
}
void SetupDirtyMultisampleControl(Tables& tables) {
- FillBlock(tables[0], OFF(multisample_control), NUM(multisample_control), MultisampleControl);
+ FillBlock(tables[0], OFF(anti_alias_alpha_control), NUM(anti_alias_alpha_control),
+ MultisampleControl);
}
void SetupDirtyRasterizeEnable(Tables& tables) {
@@ -168,7 +169,7 @@ void SetupDirtyFragmentClampColor(Tables& tables) {
}
void SetupDirtyPointSize(Tables& tables) {
- tables[0][OFF(vp_point_size)] = PointSize;
+ tables[0][OFF(point_size_attribute)] = PointSize;
tables[0][OFF(point_size)] = PointSize;
tables[0][OFF(point_sprite_enable)] = PointSize;
}
@@ -176,28 +177,28 @@ void SetupDirtyPointSize(Tables& tables) {
void SetupDirtyLineWidth(Tables& tables) {
tables[0][OFF(line_width_smooth)] = LineWidth;
tables[0][OFF(line_width_aliased)] = LineWidth;
- tables[0][OFF(line_smooth_enable)] = LineWidth;
+ tables[0][OFF(line_anti_alias_enable)] = LineWidth;
}
void SetupDirtyClipControl(Tables& tables) {
auto& table = tables[0];
- table[OFF(screen_y_control)] = ClipControl;
+ table[OFF(window_origin)] = ClipControl;
table[OFF(depth_mode)] = ClipControl;
}
void SetupDirtyDepthClampEnabled(Tables& tables) {
- tables[0][OFF(view_volume_clip_control)] = DepthClampEnabled;
+ tables[0][OFF(viewport_clip_control)] = DepthClampEnabled;
}
void SetupDirtyMisc(Tables& tables) {
auto& table = tables[0];
- table[OFF(clip_distance_enabled)] = ClipDistances;
+ table[OFF(user_clip_enable)] = ClipDistances;
- table[OFF(front_face)] = FrontFace;
+ table[OFF(gl_front_face)] = FrontFace;
- table[OFF(cull_test_enabled)] = CullTest;
- table[OFF(cull_face)] = CullTest;
+ table[OFF(gl_cull_test_enabled)] = CullTest;
+ table[OFF(gl_cull_face)] = CullTest;
}
} // Anonymous namespace
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index 004421236..e14f9b2db 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -126,51 +126,60 @@ inline const FormatTuple& GetFormatTuple(VideoCore::Surface::PixelFormat pixel_f
inline GLenum VertexFormat(Maxwell::VertexAttribute attrib) {
switch (attrib.type) {
- case Maxwell::VertexAttribute::Type::UnsignedNorm:
- case Maxwell::VertexAttribute::Type::UnsignedScaled:
- case Maxwell::VertexAttribute::Type::UnsignedInt:
+ case Maxwell::VertexAttribute::Type::UnusedEnumDoNotUseBecauseItWillGoAway:
+ ASSERT_MSG(false, "Invalid vertex attribute type!");
+ break;
+ case Maxwell::VertexAttribute::Type::UNorm:
+ case Maxwell::VertexAttribute::Type::UScaled:
+ case Maxwell::VertexAttribute::Type::UInt:
switch (attrib.size) {
- case Maxwell::VertexAttribute::Size::Size_8:
- case Maxwell::VertexAttribute::Size::Size_8_8:
- case Maxwell::VertexAttribute::Size::Size_8_8_8:
- case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8:
+ case Maxwell::VertexAttribute::Size::Size_A8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8:
+ case Maxwell::VertexAttribute::Size::Size_G8_R8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
+ case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
return GL_UNSIGNED_BYTE;
- case Maxwell::VertexAttribute::Size::Size_16:
- case Maxwell::VertexAttribute::Size::Size_16_16:
- case Maxwell::VertexAttribute::Size::Size_16_16_16:
- case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
return GL_UNSIGNED_SHORT;
- case Maxwell::VertexAttribute::Size::Size_32:
- case Maxwell::VertexAttribute::Size::Size_32_32:
- case Maxwell::VertexAttribute::Size::Size_32_32_32:
- case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
+ case Maxwell::VertexAttribute::Size::Size_R32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
return GL_UNSIGNED_INT;
- case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
+ case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
return GL_UNSIGNED_INT_2_10_10_10_REV;
default:
break;
}
break;
- case Maxwell::VertexAttribute::Type::SignedNorm:
- case Maxwell::VertexAttribute::Type::SignedScaled:
- case Maxwell::VertexAttribute::Type::SignedInt:
+ case Maxwell::VertexAttribute::Type::SNorm:
+ case Maxwell::VertexAttribute::Type::SScaled:
+ case Maxwell::VertexAttribute::Type::SInt:
switch (attrib.size) {
- case Maxwell::VertexAttribute::Size::Size_8:
- case Maxwell::VertexAttribute::Size::Size_8_8:
- case Maxwell::VertexAttribute::Size::Size_8_8_8:
- case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8:
+ case Maxwell::VertexAttribute::Size::Size_A8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8:
+ case Maxwell::VertexAttribute::Size::Size_G8_R8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
+ case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
return GL_BYTE;
- case Maxwell::VertexAttribute::Size::Size_16:
- case Maxwell::VertexAttribute::Size::Size_16_16:
- case Maxwell::VertexAttribute::Size::Size_16_16_16:
- case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
return GL_SHORT;
- case Maxwell::VertexAttribute::Size::Size_32:
- case Maxwell::VertexAttribute::Size::Size_32_32:
- case Maxwell::VertexAttribute::Size::Size_32_32_32:
- case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
+ case Maxwell::VertexAttribute::Size::Size_R32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
return GL_INT;
- case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
+ case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
return GL_INT_2_10_10_10_REV;
default:
break;
@@ -178,17 +187,17 @@ inline GLenum VertexFormat(Maxwell::VertexAttribute attrib) {
break;
case Maxwell::VertexAttribute::Type::Float:
switch (attrib.size) {
- case Maxwell::VertexAttribute::Size::Size_16:
- case Maxwell::VertexAttribute::Size::Size_16_16:
- case Maxwell::VertexAttribute::Size::Size_16_16_16:
- case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
return GL_HALF_FLOAT;
- case Maxwell::VertexAttribute::Size::Size_32:
- case Maxwell::VertexAttribute::Size::Size_32_32:
- case Maxwell::VertexAttribute::Size::Size_32_32_32:
- case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
+ case Maxwell::VertexAttribute::Size::Size_R32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
return GL_FLOAT;
- case Maxwell::VertexAttribute::Size::Size_11_11_10:
+ case Maxwell::VertexAttribute::Size::Size_B10_G11_R11:
return GL_UNSIGNED_INT_10F_11F_11F_REV;
default:
break;
@@ -335,20 +344,20 @@ inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) {
inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
switch (equation) {
- case Maxwell::Blend::Equation::Add:
- case Maxwell::Blend::Equation::AddGL:
+ case Maxwell::Blend::Equation::Add_D3D:
+ case Maxwell::Blend::Equation::Add_GL:
return GL_FUNC_ADD;
- case Maxwell::Blend::Equation::Subtract:
- case Maxwell::Blend::Equation::SubtractGL:
+ case Maxwell::Blend::Equation::Subtract_D3D:
+ case Maxwell::Blend::Equation::Subtract_GL:
return GL_FUNC_SUBTRACT;
- case Maxwell::Blend::Equation::ReverseSubtract:
- case Maxwell::Blend::Equation::ReverseSubtractGL:
+ case Maxwell::Blend::Equation::ReverseSubtract_D3D:
+ case Maxwell::Blend::Equation::ReverseSubtract_GL:
return GL_FUNC_REVERSE_SUBTRACT;
- case Maxwell::Blend::Equation::Min:
- case Maxwell::Blend::Equation::MinGL:
+ case Maxwell::Blend::Equation::Min_D3D:
+ case Maxwell::Blend::Equation::Min_GL:
return GL_MIN;
- case Maxwell::Blend::Equation::Max:
- case Maxwell::Blend::Equation::MaxGL:
+ case Maxwell::Blend::Equation::Max_D3D:
+ case Maxwell::Blend::Equation::Max_GL:
return GL_MAX;
}
UNIMPLEMENTED_MSG("Unimplemented blend equation={}", equation);
@@ -357,62 +366,62 @@ inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
switch (factor) {
- case Maxwell::Blend::Factor::Zero:
- case Maxwell::Blend::Factor::ZeroGL:
+ case Maxwell::Blend::Factor::Zero_D3D:
+ case Maxwell::Blend::Factor::Zero_GL:
return GL_ZERO;
- case Maxwell::Blend::Factor::One:
- case Maxwell::Blend::Factor::OneGL:
+ case Maxwell::Blend::Factor::One_D3D:
+ case Maxwell::Blend::Factor::One_GL:
return GL_ONE;
- case Maxwell::Blend::Factor::SourceColor:
- case Maxwell::Blend::Factor::SourceColorGL:
+ case Maxwell::Blend::Factor::SourceColor_D3D:
+ case Maxwell::Blend::Factor::SourceColor_GL:
return GL_SRC_COLOR;
- case Maxwell::Blend::Factor::OneMinusSourceColor:
- case Maxwell::Blend::Factor::OneMinusSourceColorGL:
+ case Maxwell::Blend::Factor::OneMinusSourceColor_D3D:
+ case Maxwell::Blend::Factor::OneMinusSourceColor_GL:
return GL_ONE_MINUS_SRC_COLOR;
- case Maxwell::Blend::Factor::SourceAlpha:
- case Maxwell::Blend::Factor::SourceAlphaGL:
+ case Maxwell::Blend::Factor::SourceAlpha_D3D:
+ case Maxwell::Blend::Factor::SourceAlpha_GL:
return GL_SRC_ALPHA;
- case Maxwell::Blend::Factor::OneMinusSourceAlpha:
- case Maxwell::Blend::Factor::OneMinusSourceAlphaGL:
+ case Maxwell::Blend::Factor::OneMinusSourceAlpha_D3D:
+ case Maxwell::Blend::Factor::OneMinusSourceAlpha_GL:
return GL_ONE_MINUS_SRC_ALPHA;
- case Maxwell::Blend::Factor::DestAlpha:
- case Maxwell::Blend::Factor::DestAlphaGL:
+ case Maxwell::Blend::Factor::DestAlpha_D3D:
+ case Maxwell::Blend::Factor::DestAlpha_GL:
return GL_DST_ALPHA;
- case Maxwell::Blend::Factor::OneMinusDestAlpha:
- case Maxwell::Blend::Factor::OneMinusDestAlphaGL:
+ case Maxwell::Blend::Factor::OneMinusDestAlpha_D3D:
+ case Maxwell::Blend::Factor::OneMinusDestAlpha_GL:
return GL_ONE_MINUS_DST_ALPHA;
- case Maxwell::Blend::Factor::DestColor:
- case Maxwell::Blend::Factor::DestColorGL:
+ case Maxwell::Blend::Factor::DestColor_D3D:
+ case Maxwell::Blend::Factor::DestColor_GL:
return GL_DST_COLOR;
- case Maxwell::Blend::Factor::OneMinusDestColor:
- case Maxwell::Blend::Factor::OneMinusDestColorGL:
+ case Maxwell::Blend::Factor::OneMinusDestColor_D3D:
+ case Maxwell::Blend::Factor::OneMinusDestColor_GL:
return GL_ONE_MINUS_DST_COLOR;
- case Maxwell::Blend::Factor::SourceAlphaSaturate:
- case Maxwell::Blend::Factor::SourceAlphaSaturateGL:
+ case Maxwell::Blend::Factor::SourceAlphaSaturate_D3D:
+ case Maxwell::Blend::Factor::SourceAlphaSaturate_GL:
return GL_SRC_ALPHA_SATURATE;
- case Maxwell::Blend::Factor::Source1Color:
- case Maxwell::Blend::Factor::Source1ColorGL:
+ case Maxwell::Blend::Factor::Source1Color_D3D:
+ case Maxwell::Blend::Factor::Source1Color_GL:
return GL_SRC1_COLOR;
- case Maxwell::Blend::Factor::OneMinusSource1Color:
- case Maxwell::Blend::Factor::OneMinusSource1ColorGL:
+ case Maxwell::Blend::Factor::OneMinusSource1Color_D3D:
+ case Maxwell::Blend::Factor::OneMinusSource1Color_GL:
return GL_ONE_MINUS_SRC1_COLOR;
- case Maxwell::Blend::Factor::Source1Alpha:
- case Maxwell::Blend::Factor::Source1AlphaGL:
+ case Maxwell::Blend::Factor::Source1Alpha_D3D:
+ case Maxwell::Blend::Factor::Source1Alpha_GL:
return GL_SRC1_ALPHA;
- case Maxwell::Blend::Factor::OneMinusSource1Alpha:
- case Maxwell::Blend::Factor::OneMinusSource1AlphaGL:
+ case Maxwell::Blend::Factor::OneMinusSource1Alpha_D3D:
+ case Maxwell::Blend::Factor::OneMinusSource1Alpha_GL:
return GL_ONE_MINUS_SRC1_ALPHA;
- case Maxwell::Blend::Factor::ConstantColor:
- case Maxwell::Blend::Factor::ConstantColorGL:
+ case Maxwell::Blend::Factor::BlendFactor_D3D:
+ case Maxwell::Blend::Factor::ConstantColor_GL:
return GL_CONSTANT_COLOR;
- case Maxwell::Blend::Factor::OneMinusConstantColor:
- case Maxwell::Blend::Factor::OneMinusConstantColorGL:
+ case Maxwell::Blend::Factor::OneMinusBlendFactor_D3D:
+ case Maxwell::Blend::Factor::OneMinusConstantColor_GL:
return GL_ONE_MINUS_CONSTANT_COLOR;
- case Maxwell::Blend::Factor::ConstantAlpha:
- case Maxwell::Blend::Factor::ConstantAlphaGL:
+ case Maxwell::Blend::Factor::BothSourceAlpha_D3D:
+ case Maxwell::Blend::Factor::ConstantAlpha_GL:
return GL_CONSTANT_ALPHA;
- case Maxwell::Blend::Factor::OneMinusConstantAlpha:
- case Maxwell::Blend::Factor::OneMinusConstantAlphaGL:
+ case Maxwell::Blend::Factor::OneMinusBothSourceAlpha_D3D:
+ case Maxwell::Blend::Factor::OneMinusConstantAlpha_GL:
return GL_ONE_MINUS_CONSTANT_ALPHA;
}
UNIMPLEMENTED_MSG("Unimplemented blend factor={}", factor);
@@ -421,60 +430,60 @@ inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) {
switch (comparison) {
- case Maxwell::ComparisonOp::Never:
- case Maxwell::ComparisonOp::NeverOld:
+ case Maxwell::ComparisonOp::Never_D3D:
+ case Maxwell::ComparisonOp::Never_GL:
return GL_NEVER;
- case Maxwell::ComparisonOp::Less:
- case Maxwell::ComparisonOp::LessOld:
+ case Maxwell::ComparisonOp::Less_D3D:
+ case Maxwell::ComparisonOp::Less_GL:
return GL_LESS;
- case Maxwell::ComparisonOp::Equal:
- case Maxwell::ComparisonOp::EqualOld:
+ case Maxwell::ComparisonOp::Equal_D3D:
+ case Maxwell::ComparisonOp::Equal_GL:
return GL_EQUAL;
- case Maxwell::ComparisonOp::LessEqual:
- case Maxwell::ComparisonOp::LessEqualOld:
+ case Maxwell::ComparisonOp::LessEqual_D3D:
+ case Maxwell::ComparisonOp::LessEqual_GL:
return GL_LEQUAL;
- case Maxwell::ComparisonOp::Greater:
- case Maxwell::ComparisonOp::GreaterOld:
+ case Maxwell::ComparisonOp::Greater_D3D:
+ case Maxwell::ComparisonOp::Greater_GL:
return GL_GREATER;
- case Maxwell::ComparisonOp::NotEqual:
- case Maxwell::ComparisonOp::NotEqualOld:
+ case Maxwell::ComparisonOp::NotEqual_D3D:
+ case Maxwell::ComparisonOp::NotEqual_GL:
return GL_NOTEQUAL;
- case Maxwell::ComparisonOp::GreaterEqual:
- case Maxwell::ComparisonOp::GreaterEqualOld:
+ case Maxwell::ComparisonOp::GreaterEqual_D3D:
+ case Maxwell::ComparisonOp::GreaterEqual_GL:
return GL_GEQUAL;
- case Maxwell::ComparisonOp::Always:
- case Maxwell::ComparisonOp::AlwaysOld:
+ case Maxwell::ComparisonOp::Always_D3D:
+ case Maxwell::ComparisonOp::Always_GL:
return GL_ALWAYS;
}
UNIMPLEMENTED_MSG("Unimplemented comparison op={}", comparison);
return GL_ALWAYS;
}
-inline GLenum StencilOp(Maxwell::StencilOp stencil) {
+inline GLenum StencilOp(Maxwell::StencilOp::Op stencil) {
switch (stencil) {
- case Maxwell::StencilOp::Keep:
- case Maxwell::StencilOp::KeepOGL:
+ case Maxwell::StencilOp::Op::Keep_D3D:
+ case Maxwell::StencilOp::Op::Keep_GL:
return GL_KEEP;
- case Maxwell::StencilOp::Zero:
- case Maxwell::StencilOp::ZeroOGL:
+ case Maxwell::StencilOp::Op::Zero_D3D:
+ case Maxwell::StencilOp::Op::Zero_GL:
return GL_ZERO;
- case Maxwell::StencilOp::Replace:
- case Maxwell::StencilOp::ReplaceOGL:
+ case Maxwell::StencilOp::Op::Replace_D3D:
+ case Maxwell::StencilOp::Op::Replace_GL:
return GL_REPLACE;
- case Maxwell::StencilOp::Incr:
- case Maxwell::StencilOp::IncrOGL:
+ case Maxwell::StencilOp::Op::IncrSaturate_D3D:
+ case Maxwell::StencilOp::Op::IncrSaturate_GL:
return GL_INCR;
- case Maxwell::StencilOp::Decr:
- case Maxwell::StencilOp::DecrOGL:
+ case Maxwell::StencilOp::Op::DecrSaturate_D3D:
+ case Maxwell::StencilOp::Op::DecrSaturate_GL:
return GL_DECR;
- case Maxwell::StencilOp::Invert:
- case Maxwell::StencilOp::InvertOGL:
+ case Maxwell::StencilOp::Op::Invert_D3D:
+ case Maxwell::StencilOp::Op::Invert_GL:
return GL_INVERT;
- case Maxwell::StencilOp::IncrWrap:
- case Maxwell::StencilOp::IncrWrapOGL:
+ case Maxwell::StencilOp::Op::Incr_D3D:
+ case Maxwell::StencilOp::Op::Incr_GL:
return GL_INCR_WRAP;
- case Maxwell::StencilOp::DecrWrap:
- case Maxwell::StencilOp::DecrWrapOGL:
+ case Maxwell::StencilOp::Op::Decr_D3D:
+ case Maxwell::StencilOp::Op::Decr_GL:
return GL_DECR_WRAP;
}
UNIMPLEMENTED_MSG("Unimplemented stencil op={}", stencil);
@@ -505,39 +514,39 @@ inline GLenum CullFace(Maxwell::CullFace cull_face) {
return GL_BACK;
}
-inline GLenum LogicOp(Maxwell::LogicOperation operation) {
+inline GLenum LogicOp(Maxwell::LogicOp::Op operation) {
switch (operation) {
- case Maxwell::LogicOperation::Clear:
+ case Maxwell::LogicOp::Op::Clear:
return GL_CLEAR;
- case Maxwell::LogicOperation::And:
+ case Maxwell::LogicOp::Op::And:
return GL_AND;
- case Maxwell::LogicOperation::AndReverse:
+ case Maxwell::LogicOp::Op::AndReverse:
return GL_AND_REVERSE;
- case Maxwell::LogicOperation::Copy:
+ case Maxwell::LogicOp::Op::Copy:
return GL_COPY;
- case Maxwell::LogicOperation::AndInverted:
+ case Maxwell::LogicOp::Op::AndInverted:
return GL_AND_INVERTED;
- case Maxwell::LogicOperation::NoOp:
+ case Maxwell::LogicOp::Op::NoOp:
return GL_NOOP;
- case Maxwell::LogicOperation::Xor:
+ case Maxwell::LogicOp::Op::Xor:
return GL_XOR;
- case Maxwell::LogicOperation::Or:
+ case Maxwell::LogicOp::Op::Or:
return GL_OR;
- case Maxwell::LogicOperation::Nor:
+ case Maxwell::LogicOp::Op::Nor:
return GL_NOR;
- case Maxwell::LogicOperation::Equiv:
+ case Maxwell::LogicOp::Op::Equiv:
return GL_EQUIV;
- case Maxwell::LogicOperation::Invert:
+ case Maxwell::LogicOp::Op::Invert:
return GL_INVERT;
- case Maxwell::LogicOperation::OrReverse:
+ case Maxwell::LogicOp::Op::OrReverse:
return GL_OR_REVERSE;
- case Maxwell::LogicOperation::CopyInverted:
+ case Maxwell::LogicOp::Op::CopyInverted:
return GL_COPY_INVERTED;
- case Maxwell::LogicOperation::OrInverted:
+ case Maxwell::LogicOp::Op::OrInverted:
return GL_OR_INVERTED;
- case Maxwell::LogicOperation::Nand:
+ case Maxwell::LogicOp::Op::Nand:
return GL_NAND;
- case Maxwell::LogicOperation::Set:
+ case Maxwell::LogicOp::Op::Set:
return GL_SET;
}
UNIMPLEMENTED_MSG("Unimplemented logic operation={}", operation);
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
index 733b454de..eab1b8f93 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
@@ -34,14 +34,15 @@ constexpr std::array POLYGON_OFFSET_ENABLE_LUT = {
};
void RefreshXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs) {
- std::ranges::transform(regs.tfb_layouts, state.layouts.begin(), [](const auto& layout) {
- return VideoCommon::TransformFeedbackState::Layout{
- .stream = layout.stream,
- .varying_count = layout.varying_count,
- .stride = layout.stride,
- };
- });
- state.varyings = regs.tfb_varying_locs;
+ std::ranges::transform(regs.transform_feedback.controls, state.layouts.begin(),
+ [](const auto& layout) {
+ return VideoCommon::TransformFeedbackState::Layout{
+ .stream = layout.stream,
+ .varying_count = layout.varying_count,
+ .stride = layout.stride,
+ };
+ });
+ state.varyings = regs.stream_out_layout;
}
} // Anonymous namespace
@@ -58,33 +59,38 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d,
raw1 = 0;
extended_dynamic_state.Assign(has_extended_dynamic_state ? 1 : 0);
dynamic_vertex_input.Assign(has_dynamic_vertex_input ? 1 : 0);
- xfb_enabled.Assign(regs.tfb_enabled != 0);
+ xfb_enabled.Assign(regs.transform_feedback_enabled != 0);
primitive_restart_enable.Assign(regs.primitive_restart.enabled != 0 ? 1 : 0);
depth_bias_enable.Assign(enabled_lut[POLYGON_OFFSET_ENABLE_LUT[topology_index]] != 0 ? 1 : 0);
- depth_clamp_disabled.Assign(regs.view_volume_clip_control.depth_clamp_disabled.Value());
+ depth_clamp_disabled.Assign(regs.viewport_clip_control.geometry_clip ==
+ Maxwell::ViewportClipControl::GeometryClip::Passthrough ||
+ regs.viewport_clip_control.geometry_clip ==
+ Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ ||
+ regs.viewport_clip_control.geometry_clip ==
+ Maxwell::ViewportClipControl::GeometryClip::FrustumZ);
ndc_minus_one_to_one.Assign(regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1 : 0);
polygon_mode.Assign(PackPolygonMode(regs.polygon_mode_front));
patch_control_points_minus_one.Assign(regs.patch_vertices - 1);
- tessellation_primitive.Assign(static_cast<u32>(regs.tess_mode.prim.Value()));
- tessellation_spacing.Assign(static_cast<u32>(regs.tess_mode.spacing.Value()));
- tessellation_clockwise.Assign(regs.tess_mode.cw.Value());
+ tessellation_primitive.Assign(static_cast<u32>(regs.tessellation.params.domain_type.Value()));
+ tessellation_spacing.Assign(static_cast<u32>(regs.tessellation.params.spacing.Value()));
+ tessellation_clockwise.Assign(regs.tessellation.params.output_primitives.Value() !=
+ Maxwell::Tessellation::OutputPrimitves::Triangles_CCW);
logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0);
- logic_op.Assign(PackLogicOp(regs.logic_op.operation));
+ logic_op.Assign(PackLogicOp(regs.logic_op.op));
topology.Assign(regs.draw.topology);
- msaa_mode.Assign(regs.multisample_mode);
+ msaa_mode.Assign(regs.anti_alias_samples_mode);
raw2 = 0;
rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0);
const auto test_func =
- regs.alpha_test_enabled != 0 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always;
+ regs.alpha_test_enabled != 0 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always_GL;
alpha_test_func.Assign(PackComparisonOp(test_func));
- early_z.Assign(regs.force_early_fragment_tests != 0 ? 1 : 0);
+ early_z.Assign(regs.mandated_early_z != 0 ? 1 : 0);
depth_enabled.Assign(regs.zeta_enable != 0 ? 1 : 0);
depth_format.Assign(static_cast<u32>(regs.zeta.format));
- y_negate.Assign(regs.screen_y_control.y_negate != 0 ? 1 : 0);
- provoking_vertex_last.Assign(regs.provoking_vertex_last != 0 ? 1 : 0);
- conservative_raster_enable.Assign(regs.conservative_raster_enable != 0 ? 1 : 0);
- smooth_lines.Assign(regs.line_smooth_enable != 0 ? 1 : 0);
+ y_negate.Assign(regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft ? 1 : 0);
+ provoking_vertex_last.Assign(regs.provoking_vertex == Maxwell::ProvokingVertex::Last ? 1 : 0);
+ smooth_lines.Assign(regs.line_anti_alias_enable != 0 ? 1 : 0);
for (size_t i = 0; i < regs.rt.size(); ++i) {
color_formats[i] = static_cast<u8>(regs.rt[i].format);
@@ -116,8 +122,8 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d,
maxwell3d.dirty.flags[Dirty::VertexInput] = false;
enabled_divisors = 0;
for (size_t index = 0; index < Maxwell::NumVertexArrays; ++index) {
- const bool is_enabled = regs.instanced_arrays.IsInstancingEnabled(index);
- binding_divisors[index] = is_enabled ? regs.vertex_array[index].divisor : 0;
+ const bool is_enabled = regs.vertex_stream_instances.IsInstancingEnabled(index);
+ binding_divisors[index] = is_enabled ? regs.vertex_streams[index].frequency : 0;
enabled_divisors |= (is_enabled ? u64{1} : 0) << index;
}
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
@@ -164,17 +170,17 @@ void FixedPipelineState::BlendingAttachment::Refresh(const Maxwell& regs, size_t
// TODO: C++20 Use templated lambda to deduplicate code
- if (!regs.independent_blend_enable) {
- const auto& src = regs.blend;
- if (!src.enable[index]) {
+ if (!regs.blend_per_target_enabled) {
+ if (!regs.blend.enable[index]) {
return;
}
- equation_rgb.Assign(PackBlendEquation(src.equation_rgb));
- equation_a.Assign(PackBlendEquation(src.equation_a));
- factor_source_rgb.Assign(PackBlendFactor(src.factor_source_rgb));
- factor_dest_rgb.Assign(PackBlendFactor(src.factor_dest_rgb));
- factor_source_a.Assign(PackBlendFactor(src.factor_source_a));
- factor_dest_a.Assign(PackBlendFactor(src.factor_dest_a));
+ const auto& src = regs.blend;
+ equation_rgb.Assign(PackBlendEquation(src.color_op));
+ equation_a.Assign(PackBlendEquation(src.alpha_op));
+ factor_source_rgb.Assign(PackBlendFactor(src.color_source));
+ factor_dest_rgb.Assign(PackBlendFactor(src.color_dest));
+ factor_source_a.Assign(PackBlendFactor(src.alpha_source));
+ factor_dest_a.Assign(PackBlendFactor(src.alpha_dest));
enable.Assign(1);
return;
}
@@ -182,34 +188,34 @@ void FixedPipelineState::BlendingAttachment::Refresh(const Maxwell& regs, size_t
if (!regs.blend.enable[index]) {
return;
}
- const auto& src = regs.independent_blend[index];
- equation_rgb.Assign(PackBlendEquation(src.equation_rgb));
- equation_a.Assign(PackBlendEquation(src.equation_a));
- factor_source_rgb.Assign(PackBlendFactor(src.factor_source_rgb));
- factor_dest_rgb.Assign(PackBlendFactor(src.factor_dest_rgb));
- factor_source_a.Assign(PackBlendFactor(src.factor_source_a));
- factor_dest_a.Assign(PackBlendFactor(src.factor_dest_a));
+ const auto& src = regs.blend_per_target[index];
+ equation_rgb.Assign(PackBlendEquation(src.color_op));
+ equation_a.Assign(PackBlendEquation(src.alpha_op));
+ factor_source_rgb.Assign(PackBlendFactor(src.color_source));
+ factor_dest_rgb.Assign(PackBlendFactor(src.color_dest));
+ factor_source_a.Assign(PackBlendFactor(src.alpha_source));
+ factor_dest_a.Assign(PackBlendFactor(src.alpha_dest));
enable.Assign(1);
}
void FixedPipelineState::DynamicState::Refresh(const Maxwell& regs) {
- u32 packed_front_face = PackFrontFace(regs.front_face);
- if (regs.screen_y_control.triangle_rast_flip != 0) {
+ u32 packed_front_face = PackFrontFace(regs.gl_front_face);
+ if (regs.window_origin.flip_y != 0) {
// Flip front face
packed_front_face = 1 - packed_front_face;
}
raw1 = 0;
raw2 = 0;
- front.action_stencil_fail.Assign(PackStencilOp(regs.stencil_front_op_fail));
- front.action_depth_fail.Assign(PackStencilOp(regs.stencil_front_op_zfail));
- front.action_depth_pass.Assign(PackStencilOp(regs.stencil_front_op_zpass));
- front.test_func.Assign(PackComparisonOp(regs.stencil_front_func_func));
+ front.action_stencil_fail.Assign(PackStencilOp(regs.stencil_front_op.fail));
+ front.action_depth_fail.Assign(PackStencilOp(regs.stencil_front_op.zfail));
+ front.action_depth_pass.Assign(PackStencilOp(regs.stencil_front_op.zpass));
+ front.test_func.Assign(PackComparisonOp(regs.stencil_front_op.func));
if (regs.stencil_two_side_enable) {
- back.action_stencil_fail.Assign(PackStencilOp(regs.stencil_back_op_fail));
- back.action_depth_fail.Assign(PackStencilOp(regs.stencil_back_op_zfail));
- back.action_depth_pass.Assign(PackStencilOp(regs.stencil_back_op_zpass));
- back.test_func.Assign(PackComparisonOp(regs.stencil_back_func_func));
+ back.action_stencil_fail.Assign(PackStencilOp(regs.stencil_back_op.fail));
+ back.action_depth_fail.Assign(PackStencilOp(regs.stencil_back_op.zfail));
+ back.action_depth_pass.Assign(PackStencilOp(regs.stencil_back_op.zpass));
+ back.test_func.Assign(PackComparisonOp(regs.stencil_back_op.func));
} else {
back.action_stencil_fail.Assign(front.action_stencil_fail);
back.action_depth_fail.Assign(front.action_depth_fail);
@@ -222,9 +228,9 @@ void FixedPipelineState::DynamicState::Refresh(const Maxwell& regs) {
depth_test_enable.Assign(regs.depth_test_enable);
front_face.Assign(packed_front_face);
depth_test_func.Assign(PackComparisonOp(regs.depth_test_func));
- cull_face.Assign(PackCullFace(regs.cull_face));
- cull_enable.Assign(regs.cull_test_enabled != 0 ? 1 : 0);
- std::ranges::transform(regs.vertex_array, vertex_strides.begin(), [](const auto& array) {
+ cull_face.Assign(PackCullFace(regs.gl_cull_face));
+ cull_enable.Assign(regs.gl_cull_test_enabled != 0 ? 1 : 0);
+ std::ranges::transform(regs.vertex_streams, vertex_strides.begin(), [](const auto& array) {
return static_cast<u16>(array.stride.Value());
});
}
@@ -251,41 +257,42 @@ Maxwell::ComparisonOp FixedPipelineState::UnpackComparisonOp(u32 packed) noexcep
return static_cast<Maxwell::ComparisonOp>(packed + 1);
}
-u32 FixedPipelineState::PackStencilOp(Maxwell::StencilOp op) noexcept {
+u32 FixedPipelineState::PackStencilOp(Maxwell::StencilOp::Op op) noexcept {
switch (op) {
- case Maxwell::StencilOp::Keep:
- case Maxwell::StencilOp::KeepOGL:
+ case Maxwell::StencilOp::Op::Keep_D3D:
+ case Maxwell::StencilOp::Op::Keep_GL:
return 0;
- case Maxwell::StencilOp::Zero:
- case Maxwell::StencilOp::ZeroOGL:
+ case Maxwell::StencilOp::Op::Zero_D3D:
+ case Maxwell::StencilOp::Op::Zero_GL:
return 1;
- case Maxwell::StencilOp::Replace:
- case Maxwell::StencilOp::ReplaceOGL:
+ case Maxwell::StencilOp::Op::Replace_D3D:
+ case Maxwell::StencilOp::Op::Replace_GL:
return 2;
- case Maxwell::StencilOp::Incr:
- case Maxwell::StencilOp::IncrOGL:
+ case Maxwell::StencilOp::Op::IncrSaturate_D3D:
+ case Maxwell::StencilOp::Op::IncrSaturate_GL:
return 3;
- case Maxwell::StencilOp::Decr:
- case Maxwell::StencilOp::DecrOGL:
+ case Maxwell::StencilOp::Op::DecrSaturate_D3D:
+ case Maxwell::StencilOp::Op::DecrSaturate_GL:
return 4;
- case Maxwell::StencilOp::Invert:
- case Maxwell::StencilOp::InvertOGL:
+ case Maxwell::StencilOp::Op::Invert_D3D:
+ case Maxwell::StencilOp::Op::Invert_GL:
return 5;
- case Maxwell::StencilOp::IncrWrap:
- case Maxwell::StencilOp::IncrWrapOGL:
+ case Maxwell::StencilOp::Op::Incr_D3D:
+ case Maxwell::StencilOp::Op::Incr_GL:
return 6;
- case Maxwell::StencilOp::DecrWrap:
- case Maxwell::StencilOp::DecrWrapOGL:
+ case Maxwell::StencilOp::Op::Decr_D3D:
+ case Maxwell::StencilOp::Op::Decr_GL:
return 7;
}
return 0;
}
-Maxwell::StencilOp FixedPipelineState::UnpackStencilOp(u32 packed) noexcept {
- static constexpr std::array LUT = {Maxwell::StencilOp::Keep, Maxwell::StencilOp::Zero,
- Maxwell::StencilOp::Replace, Maxwell::StencilOp::Incr,
- Maxwell::StencilOp::Decr, Maxwell::StencilOp::Invert,
- Maxwell::StencilOp::IncrWrap, Maxwell::StencilOp::DecrWrap};
+Maxwell::StencilOp::Op FixedPipelineState::UnpackStencilOp(u32 packed) noexcept {
+ static constexpr std::array LUT = {
+ Maxwell::StencilOp::Op::Keep_D3D, Maxwell::StencilOp::Op::Zero_D3D,
+ Maxwell::StencilOp::Op::Replace_D3D, Maxwell::StencilOp::Op::IncrSaturate_D3D,
+ Maxwell::StencilOp::Op::DecrSaturate_D3D, Maxwell::StencilOp::Op::Invert_D3D,
+ Maxwell::StencilOp::Op::Incr_D3D, Maxwell::StencilOp::Op::Decr_D3D};
return LUT[packed];
}
@@ -318,30 +325,30 @@ Maxwell::PolygonMode FixedPipelineState::UnpackPolygonMode(u32 packed) noexcept
return static_cast<Maxwell::PolygonMode>(packed + 0x1B00);
}
-u32 FixedPipelineState::PackLogicOp(Maxwell::LogicOperation op) noexcept {
+u32 FixedPipelineState::PackLogicOp(Maxwell::LogicOp::Op op) noexcept {
return static_cast<u32>(op) - 0x1500;
}
-Maxwell::LogicOperation FixedPipelineState::UnpackLogicOp(u32 packed) noexcept {
- return static_cast<Maxwell::LogicOperation>(packed + 0x1500);
+Maxwell::LogicOp::Op FixedPipelineState::UnpackLogicOp(u32 packed) noexcept {
+ return static_cast<Maxwell::LogicOp::Op>(packed + 0x1500);
}
u32 FixedPipelineState::PackBlendEquation(Maxwell::Blend::Equation equation) noexcept {
switch (equation) {
- case Maxwell::Blend::Equation::Add:
- case Maxwell::Blend::Equation::AddGL:
+ case Maxwell::Blend::Equation::Add_D3D:
+ case Maxwell::Blend::Equation::Add_GL:
return 0;
- case Maxwell::Blend::Equation::Subtract:
- case Maxwell::Blend::Equation::SubtractGL:
+ case Maxwell::Blend::Equation::Subtract_D3D:
+ case Maxwell::Blend::Equation::Subtract_GL:
return 1;
- case Maxwell::Blend::Equation::ReverseSubtract:
- case Maxwell::Blend::Equation::ReverseSubtractGL:
+ case Maxwell::Blend::Equation::ReverseSubtract_D3D:
+ case Maxwell::Blend::Equation::ReverseSubtract_GL:
return 2;
- case Maxwell::Blend::Equation::Min:
- case Maxwell::Blend::Equation::MinGL:
+ case Maxwell::Blend::Equation::Min_D3D:
+ case Maxwell::Blend::Equation::Min_GL:
return 3;
- case Maxwell::Blend::Equation::Max:
- case Maxwell::Blend::Equation::MaxGL:
+ case Maxwell::Blend::Equation::Max_D3D:
+ case Maxwell::Blend::Equation::Max_GL:
return 4;
}
return 0;
@@ -349,97 +356,99 @@ u32 FixedPipelineState::PackBlendEquation(Maxwell::Blend::Equation equation) noe
Maxwell::Blend::Equation FixedPipelineState::UnpackBlendEquation(u32 packed) noexcept {
static constexpr std::array LUT = {
- Maxwell::Blend::Equation::Add, Maxwell::Blend::Equation::Subtract,
- Maxwell::Blend::Equation::ReverseSubtract, Maxwell::Blend::Equation::Min,
- Maxwell::Blend::Equation::Max};
+ Maxwell::Blend::Equation::Add_D3D, Maxwell::Blend::Equation::Subtract_D3D,
+ Maxwell::Blend::Equation::ReverseSubtract_D3D, Maxwell::Blend::Equation::Min_D3D,
+ Maxwell::Blend::Equation::Max_D3D};
return LUT[packed];
}
u32 FixedPipelineState::PackBlendFactor(Maxwell::Blend::Factor factor) noexcept {
switch (factor) {
- case Maxwell::Blend::Factor::Zero:
- case Maxwell::Blend::Factor::ZeroGL:
+ case Maxwell::Blend::Factor::Zero_D3D:
+ case Maxwell::Blend::Factor::Zero_GL:
return 0;
- case Maxwell::Blend::Factor::One:
- case Maxwell::Blend::Factor::OneGL:
+ case Maxwell::Blend::Factor::One_D3D:
+ case Maxwell::Blend::Factor::One_GL:
return 1;
- case Maxwell::Blend::Factor::SourceColor:
- case Maxwell::Blend::Factor::SourceColorGL:
+ case Maxwell::Blend::Factor::SourceColor_D3D:
+ case Maxwell::Blend::Factor::SourceColor_GL:
return 2;
- case Maxwell::Blend::Factor::OneMinusSourceColor:
- case Maxwell::Blend::Factor::OneMinusSourceColorGL:
+ case Maxwell::Blend::Factor::OneMinusSourceColor_D3D:
+ case Maxwell::Blend::Factor::OneMinusSourceColor_GL:
return 3;
- case Maxwell::Blend::Factor::SourceAlpha:
- case Maxwell::Blend::Factor::SourceAlphaGL:
+ case Maxwell::Blend::Factor::SourceAlpha_D3D:
+ case Maxwell::Blend::Factor::SourceAlpha_GL:
return 4;
- case Maxwell::Blend::Factor::OneMinusSourceAlpha:
- case Maxwell::Blend::Factor::OneMinusSourceAlphaGL:
+ case Maxwell::Blend::Factor::OneMinusSourceAlpha_D3D:
+ case Maxwell::Blend::Factor::OneMinusSourceAlpha_GL:
return 5;
- case Maxwell::Blend::Factor::DestAlpha:
- case Maxwell::Blend::Factor::DestAlphaGL:
+ case Maxwell::Blend::Factor::DestAlpha_D3D:
+ case Maxwell::Blend::Factor::DestAlpha_GL:
return 6;
- case Maxwell::Blend::Factor::OneMinusDestAlpha:
- case Maxwell::Blend::Factor::OneMinusDestAlphaGL:
+ case Maxwell::Blend::Factor::OneMinusDestAlpha_D3D:
+ case Maxwell::Blend::Factor::OneMinusDestAlpha_GL:
return 7;
- case Maxwell::Blend::Factor::DestColor:
- case Maxwell::Blend::Factor::DestColorGL:
+ case Maxwell::Blend::Factor::DestColor_D3D:
+ case Maxwell::Blend::Factor::DestColor_GL:
return 8;
- case Maxwell::Blend::Factor::OneMinusDestColor:
- case Maxwell::Blend::Factor::OneMinusDestColorGL:
+ case Maxwell::Blend::Factor::OneMinusDestColor_D3D:
+ case Maxwell::Blend::Factor::OneMinusDestColor_GL:
return 9;
- case Maxwell::Blend::Factor::SourceAlphaSaturate:
- case Maxwell::Blend::Factor::SourceAlphaSaturateGL:
+ case Maxwell::Blend::Factor::SourceAlphaSaturate_D3D:
+ case Maxwell::Blend::Factor::SourceAlphaSaturate_GL:
return 10;
- case Maxwell::Blend::Factor::Source1Color:
- case Maxwell::Blend::Factor::Source1ColorGL:
+ case Maxwell::Blend::Factor::Source1Color_D3D:
+ case Maxwell::Blend::Factor::Source1Color_GL:
return 11;
- case Maxwell::Blend::Factor::OneMinusSource1Color:
- case Maxwell::Blend::Factor::OneMinusSource1ColorGL:
+ case Maxwell::Blend::Factor::OneMinusSource1Color_D3D:
+ case Maxwell::Blend::Factor::OneMinusSource1Color_GL:
return 12;
- case Maxwell::Blend::Factor::Source1Alpha:
- case Maxwell::Blend::Factor::Source1AlphaGL:
+ case Maxwell::Blend::Factor::Source1Alpha_D3D:
+ case Maxwell::Blend::Factor::Source1Alpha_GL:
return 13;
- case Maxwell::Blend::Factor::OneMinusSource1Alpha:
- case Maxwell::Blend::Factor::OneMinusSource1AlphaGL:
+ case Maxwell::Blend::Factor::OneMinusSource1Alpha_D3D:
+ case Maxwell::Blend::Factor::OneMinusSource1Alpha_GL:
return 14;
- case Maxwell::Blend::Factor::ConstantColor:
- case Maxwell::Blend::Factor::ConstantColorGL:
+ case Maxwell::Blend::Factor::BlendFactor_D3D:
+ case Maxwell::Blend::Factor::ConstantColor_GL:
return 15;
- case Maxwell::Blend::Factor::OneMinusConstantColor:
- case Maxwell::Blend::Factor::OneMinusConstantColorGL:
+ case Maxwell::Blend::Factor::OneMinusBlendFactor_D3D:
+ case Maxwell::Blend::Factor::OneMinusConstantColor_GL:
return 16;
- case Maxwell::Blend::Factor::ConstantAlpha:
- case Maxwell::Blend::Factor::ConstantAlphaGL:
+ case Maxwell::Blend::Factor::BothSourceAlpha_D3D:
+ case Maxwell::Blend::Factor::ConstantAlpha_GL:
return 17;
- case Maxwell::Blend::Factor::OneMinusConstantAlpha:
- case Maxwell::Blend::Factor::OneMinusConstantAlphaGL:
+ case Maxwell::Blend::Factor::OneMinusBothSourceAlpha_D3D:
+ case Maxwell::Blend::Factor::OneMinusConstantAlpha_GL:
return 18;
}
+ UNIMPLEMENTED_MSG("Unknown blend factor {}", static_cast<u32>(factor));
return 0;
}
Maxwell::Blend::Factor FixedPipelineState::UnpackBlendFactor(u32 packed) noexcept {
static constexpr std::array LUT = {
- Maxwell::Blend::Factor::Zero,
- Maxwell::Blend::Factor::One,
- Maxwell::Blend::Factor::SourceColor,
- Maxwell::Blend::Factor::OneMinusSourceColor,
- Maxwell::Blend::Factor::SourceAlpha,
- Maxwell::Blend::Factor::OneMinusSourceAlpha,
- Maxwell::Blend::Factor::DestAlpha,
- Maxwell::Blend::Factor::OneMinusDestAlpha,
- Maxwell::Blend::Factor::DestColor,
- Maxwell::Blend::Factor::OneMinusDestColor,
- Maxwell::Blend::Factor::SourceAlphaSaturate,
- Maxwell::Blend::Factor::Source1Color,
- Maxwell::Blend::Factor::OneMinusSource1Color,
- Maxwell::Blend::Factor::Source1Alpha,
- Maxwell::Blend::Factor::OneMinusSource1Alpha,
- Maxwell::Blend::Factor::ConstantColor,
- Maxwell::Blend::Factor::OneMinusConstantColor,
- Maxwell::Blend::Factor::ConstantAlpha,
- Maxwell::Blend::Factor::OneMinusConstantAlpha,
+ Maxwell::Blend::Factor::Zero_D3D,
+ Maxwell::Blend::Factor::One_D3D,
+ Maxwell::Blend::Factor::SourceColor_D3D,
+ Maxwell::Blend::Factor::OneMinusSourceColor_D3D,
+ Maxwell::Blend::Factor::SourceAlpha_D3D,
+ Maxwell::Blend::Factor::OneMinusSourceAlpha_D3D,
+ Maxwell::Blend::Factor::DestAlpha_D3D,
+ Maxwell::Blend::Factor::OneMinusDestAlpha_D3D,
+ Maxwell::Blend::Factor::DestColor_D3D,
+ Maxwell::Blend::Factor::OneMinusDestColor_D3D,
+ Maxwell::Blend::Factor::SourceAlphaSaturate_D3D,
+ Maxwell::Blend::Factor::Source1Color_D3D,
+ Maxwell::Blend::Factor::OneMinusSource1Color_D3D,
+ Maxwell::Blend::Factor::Source1Alpha_D3D,
+ Maxwell::Blend::Factor::OneMinusSource1Alpha_D3D,
+ Maxwell::Blend::Factor::BlendFactor_D3D,
+ Maxwell::Blend::Factor::OneMinusBlendFactor_D3D,
+ Maxwell::Blend::Factor::BothSourceAlpha_D3D,
+ Maxwell::Blend::Factor::OneMinusBothSourceAlpha_D3D,
};
+ ASSERT(packed < LUT.size());
return LUT[packed];
}
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h
index 9d60756e5..43441209c 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h
@@ -21,8 +21,8 @@ struct FixedPipelineState {
static u32 PackComparisonOp(Maxwell::ComparisonOp op) noexcept;
static Maxwell::ComparisonOp UnpackComparisonOp(u32 packed) noexcept;
- static u32 PackStencilOp(Maxwell::StencilOp op) noexcept;
- static Maxwell::StencilOp UnpackStencilOp(u32 packed) noexcept;
+ static u32 PackStencilOp(Maxwell::StencilOp::Op op) noexcept;
+ static Maxwell::StencilOp::Op UnpackStencilOp(u32 packed) noexcept;
static u32 PackCullFace(Maxwell::CullFace cull) noexcept;
static Maxwell::CullFace UnpackCullFace(u32 packed) noexcept;
@@ -33,8 +33,8 @@ struct FixedPipelineState {
static u32 PackPolygonMode(Maxwell::PolygonMode mode) noexcept;
static Maxwell::PolygonMode UnpackPolygonMode(u32 packed) noexcept;
- static u32 PackLogicOp(Maxwell::LogicOperation op) noexcept;
- static Maxwell::LogicOperation UnpackLogicOp(u32 packed) noexcept;
+ static u32 PackLogicOp(Maxwell::LogicOp::Op op) noexcept;
+ static Maxwell::LogicOp::Op UnpackLogicOp(u32 packed) noexcept;
static u32 PackBlendEquation(Maxwell::Blend::Equation equation) noexcept;
static Maxwell::Blend::Equation UnpackBlendEquation(u32 packed) noexcept;
@@ -113,15 +113,15 @@ struct FixedPipelineState {
BitField<Position + 6, 3, u32> action_depth_pass;
BitField<Position + 9, 3, u32> test_func;
- Maxwell::StencilOp ActionStencilFail() const noexcept {
+ Maxwell::StencilOp::Op ActionStencilFail() const noexcept {
return UnpackStencilOp(action_stencil_fail);
}
- Maxwell::StencilOp ActionDepthFail() const noexcept {
+ Maxwell::StencilOp::Op ActionDepthFail() const noexcept {
return UnpackStencilOp(action_depth_fail);
}
- Maxwell::StencilOp ActionDepthPass() const noexcept {
+ Maxwell::StencilOp::Op ActionDepthPass() const noexcept {
return UnpackStencilOp(action_depth_pass);
}
@@ -193,7 +193,6 @@ struct FixedPipelineState {
BitField<6, 5, u32> depth_format;
BitField<11, 1, u32> y_negate;
BitField<12, 1, u32> provoking_vertex_last;
- BitField<13, 1, u32> conservative_raster_enable;
BitField<14, 1, u32> smooth_lines;
};
std::array<u8, Maxwell::NumRenderTargets> color_formats;
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
index e7104d377..5c156087b 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
@@ -323,161 +323,182 @@ VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type,
Maxwell::VertexAttribute::Size size) {
const VkFormat format{([&]() {
switch (type) {
- case Maxwell::VertexAttribute::Type::UnsignedNorm:
+ case Maxwell::VertexAttribute::Type::UnusedEnumDoNotUseBecauseItWillGoAway:
+ ASSERT_MSG(false, "Invalid vertex attribute type!");
+ break;
+ case Maxwell::VertexAttribute::Type::UNorm:
switch (size) {
- case Maxwell::VertexAttribute::Size::Size_8:
+ case Maxwell::VertexAttribute::Size::Size_R8:
+ case Maxwell::VertexAttribute::Size::Size_A8:
return VK_FORMAT_R8_UNORM;
- case Maxwell::VertexAttribute::Size::Size_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8:
+ case Maxwell::VertexAttribute::Size::Size_G8_R8:
return VK_FORMAT_R8G8_UNORM;
- case Maxwell::VertexAttribute::Size::Size_8_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
return VK_FORMAT_R8G8B8_UNORM;
- case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
+ case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
return VK_FORMAT_R8G8B8A8_UNORM;
- case Maxwell::VertexAttribute::Size::Size_16:
+ case Maxwell::VertexAttribute::Size::Size_R16:
return VK_FORMAT_R16_UNORM;
- case Maxwell::VertexAttribute::Size::Size_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16:
return VK_FORMAT_R16G16_UNORM;
- case Maxwell::VertexAttribute::Size::Size_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
return VK_FORMAT_R16G16B16_UNORM;
- case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
return VK_FORMAT_R16G16B16A16_UNORM;
- case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
+ case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
default:
break;
}
break;
- case Maxwell::VertexAttribute::Type::SignedNorm:
+ case Maxwell::VertexAttribute::Type::SNorm:
switch (size) {
- case Maxwell::VertexAttribute::Size::Size_8:
+ case Maxwell::VertexAttribute::Size::Size_R8:
+ case Maxwell::VertexAttribute::Size::Size_A8:
return VK_FORMAT_R8_SNORM;
- case Maxwell::VertexAttribute::Size::Size_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8:
+ case Maxwell::VertexAttribute::Size::Size_G8_R8:
return VK_FORMAT_R8G8_SNORM;
- case Maxwell::VertexAttribute::Size::Size_8_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
return VK_FORMAT_R8G8B8_SNORM;
- case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
+ case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
return VK_FORMAT_R8G8B8A8_SNORM;
- case Maxwell::VertexAttribute::Size::Size_16:
+ case Maxwell::VertexAttribute::Size::Size_R16:
return VK_FORMAT_R16_SNORM;
- case Maxwell::VertexAttribute::Size::Size_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16:
return VK_FORMAT_R16G16_SNORM;
- case Maxwell::VertexAttribute::Size::Size_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
return VK_FORMAT_R16G16B16_SNORM;
- case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
return VK_FORMAT_R16G16B16A16_SNORM;
- case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
+ case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
return VK_FORMAT_A2B10G10R10_SNORM_PACK32;
default:
break;
}
break;
- case Maxwell::VertexAttribute::Type::UnsignedScaled:
+ case Maxwell::VertexAttribute::Type::UScaled:
switch (size) {
- case Maxwell::VertexAttribute::Size::Size_8:
+ case Maxwell::VertexAttribute::Size::Size_R8:
+ case Maxwell::VertexAttribute::Size::Size_A8:
return VK_FORMAT_R8_USCALED;
- case Maxwell::VertexAttribute::Size::Size_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8:
+ case Maxwell::VertexAttribute::Size::Size_G8_R8:
return VK_FORMAT_R8G8_USCALED;
- case Maxwell::VertexAttribute::Size::Size_8_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
return VK_FORMAT_R8G8B8_USCALED;
- case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
+ case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
return VK_FORMAT_R8G8B8A8_USCALED;
- case Maxwell::VertexAttribute::Size::Size_16:
+ case Maxwell::VertexAttribute::Size::Size_R16:
return VK_FORMAT_R16_USCALED;
- case Maxwell::VertexAttribute::Size::Size_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16:
return VK_FORMAT_R16G16_USCALED;
- case Maxwell::VertexAttribute::Size::Size_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
return VK_FORMAT_R16G16B16_USCALED;
- case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
return VK_FORMAT_R16G16B16A16_USCALED;
- case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
+ case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
return VK_FORMAT_A2B10G10R10_USCALED_PACK32;
default:
break;
}
break;
- case Maxwell::VertexAttribute::Type::SignedScaled:
+ case Maxwell::VertexAttribute::Type::SScaled:
switch (size) {
- case Maxwell::VertexAttribute::Size::Size_8:
+ case Maxwell::VertexAttribute::Size::Size_R8:
+ case Maxwell::VertexAttribute::Size::Size_A8:
return VK_FORMAT_R8_SSCALED;
- case Maxwell::VertexAttribute::Size::Size_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8:
+ case Maxwell::VertexAttribute::Size::Size_G8_R8:
return VK_FORMAT_R8G8_SSCALED;
- case Maxwell::VertexAttribute::Size::Size_8_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
return VK_FORMAT_R8G8B8_SSCALED;
- case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
+ case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
return VK_FORMAT_R8G8B8A8_SSCALED;
- case Maxwell::VertexAttribute::Size::Size_16:
+ case Maxwell::VertexAttribute::Size::Size_R16:
return VK_FORMAT_R16_SSCALED;
- case Maxwell::VertexAttribute::Size::Size_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16:
return VK_FORMAT_R16G16_SSCALED;
- case Maxwell::VertexAttribute::Size::Size_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
return VK_FORMAT_R16G16B16_SSCALED;
- case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
return VK_FORMAT_R16G16B16A16_SSCALED;
- case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
+ case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
return VK_FORMAT_A2B10G10R10_SSCALED_PACK32;
default:
break;
}
break;
- case Maxwell::VertexAttribute::Type::UnsignedInt:
+ case Maxwell::VertexAttribute::Type::UInt:
switch (size) {
- case Maxwell::VertexAttribute::Size::Size_8:
+ case Maxwell::VertexAttribute::Size::Size_R8:
+ case Maxwell::VertexAttribute::Size::Size_A8:
return VK_FORMAT_R8_UINT;
- case Maxwell::VertexAttribute::Size::Size_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8:
+ case Maxwell::VertexAttribute::Size::Size_G8_R8:
return VK_FORMAT_R8G8_UINT;
- case Maxwell::VertexAttribute::Size::Size_8_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
return VK_FORMAT_R8G8B8_UINT;
- case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
+ case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
return VK_FORMAT_R8G8B8A8_UINT;
- case Maxwell::VertexAttribute::Size::Size_16:
+ case Maxwell::VertexAttribute::Size::Size_R16:
return VK_FORMAT_R16_UINT;
- case Maxwell::VertexAttribute::Size::Size_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16:
return VK_FORMAT_R16G16_UINT;
- case Maxwell::VertexAttribute::Size::Size_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
return VK_FORMAT_R16G16B16_UINT;
- case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
return VK_FORMAT_R16G16B16A16_UINT;
- case Maxwell::VertexAttribute::Size::Size_32:
+ case Maxwell::VertexAttribute::Size::Size_R32:
return VK_FORMAT_R32_UINT;
- case Maxwell::VertexAttribute::Size::Size_32_32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32:
return VK_FORMAT_R32G32_UINT;
- case Maxwell::VertexAttribute::Size::Size_32_32_32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
return VK_FORMAT_R32G32B32_UINT;
- case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
return VK_FORMAT_R32G32B32A32_UINT;
- case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
+ case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
return VK_FORMAT_A2B10G10R10_UINT_PACK32;
default:
break;
}
break;
- case Maxwell::VertexAttribute::Type::SignedInt:
+ case Maxwell::VertexAttribute::Type::SInt:
switch (size) {
- case Maxwell::VertexAttribute::Size::Size_8:
+ case Maxwell::VertexAttribute::Size::Size_R8:
+ case Maxwell::VertexAttribute::Size::Size_A8:
return VK_FORMAT_R8_SINT;
- case Maxwell::VertexAttribute::Size::Size_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8:
+ case Maxwell::VertexAttribute::Size::Size_G8_R8:
return VK_FORMAT_R8G8_SINT;
- case Maxwell::VertexAttribute::Size::Size_8_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
return VK_FORMAT_R8G8B8_SINT;
- case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
+ case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
+ case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
return VK_FORMAT_R8G8B8A8_SINT;
- case Maxwell::VertexAttribute::Size::Size_16:
+ case Maxwell::VertexAttribute::Size::Size_R16:
return VK_FORMAT_R16_SINT;
- case Maxwell::VertexAttribute::Size::Size_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16:
return VK_FORMAT_R16G16_SINT;
- case Maxwell::VertexAttribute::Size::Size_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
return VK_FORMAT_R16G16B16_SINT;
- case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
return VK_FORMAT_R16G16B16A16_SINT;
- case Maxwell::VertexAttribute::Size::Size_32:
+ case Maxwell::VertexAttribute::Size::Size_R32:
return VK_FORMAT_R32_SINT;
- case Maxwell::VertexAttribute::Size::Size_32_32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32:
return VK_FORMAT_R32G32_SINT;
- case Maxwell::VertexAttribute::Size::Size_32_32_32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
return VK_FORMAT_R32G32B32_SINT;
- case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
return VK_FORMAT_R32G32B32A32_SINT;
- case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
+ case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
return VK_FORMAT_A2B10G10R10_SINT_PACK32;
default:
break;
@@ -485,23 +506,23 @@ VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type,
break;
case Maxwell::VertexAttribute::Type::Float:
switch (size) {
- case Maxwell::VertexAttribute::Size::Size_16:
+ case Maxwell::VertexAttribute::Size::Size_R16:
return VK_FORMAT_R16_SFLOAT;
- case Maxwell::VertexAttribute::Size::Size_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16:
return VK_FORMAT_R16G16_SFLOAT;
- case Maxwell::VertexAttribute::Size::Size_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
return VK_FORMAT_R16G16B16_SFLOAT;
- case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
+ case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
return VK_FORMAT_R16G16B16A16_SFLOAT;
- case Maxwell::VertexAttribute::Size::Size_32:
+ case Maxwell::VertexAttribute::Size::Size_R32:
return VK_FORMAT_R32_SFLOAT;
- case Maxwell::VertexAttribute::Size::Size_32_32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32:
return VK_FORMAT_R32G32_SFLOAT;
- case Maxwell::VertexAttribute::Size::Size_32_32_32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
return VK_FORMAT_R32G32B32_SFLOAT;
- case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
+ case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
return VK_FORMAT_R32G32B32A32_SFLOAT;
- case Maxwell::VertexAttribute::Size::Size_11_11_10:
+ case Maxwell::VertexAttribute::Size::Size_B10_G11_R11:
return VK_FORMAT_B10G11R11_UFLOAT_PACK32;
default:
break;
@@ -521,29 +542,29 @@ VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type,
VkCompareOp ComparisonOp(Maxwell::ComparisonOp comparison) {
switch (comparison) {
- case Maxwell::ComparisonOp::Never:
- case Maxwell::ComparisonOp::NeverOld:
+ case Maxwell::ComparisonOp::Never_D3D:
+ case Maxwell::ComparisonOp::Never_GL:
return VK_COMPARE_OP_NEVER;
- case Maxwell::ComparisonOp::Less:
- case Maxwell::ComparisonOp::LessOld:
+ case Maxwell::ComparisonOp::Less_D3D:
+ case Maxwell::ComparisonOp::Less_GL:
return VK_COMPARE_OP_LESS;
- case Maxwell::ComparisonOp::Equal:
- case Maxwell::ComparisonOp::EqualOld:
+ case Maxwell::ComparisonOp::Equal_D3D:
+ case Maxwell::ComparisonOp::Equal_GL:
return VK_COMPARE_OP_EQUAL;
- case Maxwell::ComparisonOp::LessEqual:
- case Maxwell::ComparisonOp::LessEqualOld:
+ case Maxwell::ComparisonOp::LessEqual_D3D:
+ case Maxwell::ComparisonOp::LessEqual_GL:
return VK_COMPARE_OP_LESS_OR_EQUAL;
- case Maxwell::ComparisonOp::Greater:
- case Maxwell::ComparisonOp::GreaterOld:
+ case Maxwell::ComparisonOp::Greater_D3D:
+ case Maxwell::ComparisonOp::Greater_GL:
return VK_COMPARE_OP_GREATER;
- case Maxwell::ComparisonOp::NotEqual:
- case Maxwell::ComparisonOp::NotEqualOld:
+ case Maxwell::ComparisonOp::NotEqual_D3D:
+ case Maxwell::ComparisonOp::NotEqual_GL:
return VK_COMPARE_OP_NOT_EQUAL;
- case Maxwell::ComparisonOp::GreaterEqual:
- case Maxwell::ComparisonOp::GreaterEqualOld:
+ case Maxwell::ComparisonOp::GreaterEqual_D3D:
+ case Maxwell::ComparisonOp::GreaterEqual_GL:
return VK_COMPARE_OP_GREATER_OR_EQUAL;
- case Maxwell::ComparisonOp::Always:
- case Maxwell::ComparisonOp::AlwaysOld:
+ case Maxwell::ComparisonOp::Always_D3D:
+ case Maxwell::ComparisonOp::Always_GL:
return VK_COMPARE_OP_ALWAYS;
}
UNIMPLEMENTED_MSG("Unimplemented comparison op={}", comparison);
@@ -563,31 +584,31 @@ VkIndexType IndexFormat(Maxwell::IndexFormat index_format) {
return {};
}
-VkStencilOp StencilOp(Maxwell::StencilOp stencil_op) {
+VkStencilOp StencilOp(Maxwell::StencilOp::Op stencil_op) {
switch (stencil_op) {
- case Maxwell::StencilOp::Keep:
- case Maxwell::StencilOp::KeepOGL:
+ case Maxwell::StencilOp::Op::Keep_D3D:
+ case Maxwell::StencilOp::Op::Keep_GL:
return VK_STENCIL_OP_KEEP;
- case Maxwell::StencilOp::Zero:
- case Maxwell::StencilOp::ZeroOGL:
+ case Maxwell::StencilOp::Op::Zero_D3D:
+ case Maxwell::StencilOp::Op::Zero_GL:
return VK_STENCIL_OP_ZERO;
- case Maxwell::StencilOp::Replace:
- case Maxwell::StencilOp::ReplaceOGL:
+ case Maxwell::StencilOp::Op::Replace_D3D:
+ case Maxwell::StencilOp::Op::Replace_GL:
return VK_STENCIL_OP_REPLACE;
- case Maxwell::StencilOp::Incr:
- case Maxwell::StencilOp::IncrOGL:
+ case Maxwell::StencilOp::Op::IncrSaturate_D3D:
+ case Maxwell::StencilOp::Op::IncrSaturate_GL:
return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
- case Maxwell::StencilOp::Decr:
- case Maxwell::StencilOp::DecrOGL:
+ case Maxwell::StencilOp::Op::DecrSaturate_D3D:
+ case Maxwell::StencilOp::Op::DecrSaturate_GL:
return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
- case Maxwell::StencilOp::Invert:
- case Maxwell::StencilOp::InvertOGL:
+ case Maxwell::StencilOp::Op::Invert_D3D:
+ case Maxwell::StencilOp::Op::Invert_GL:
return VK_STENCIL_OP_INVERT;
- case Maxwell::StencilOp::IncrWrap:
- case Maxwell::StencilOp::IncrWrapOGL:
+ case Maxwell::StencilOp::Op::Incr_D3D:
+ case Maxwell::StencilOp::Op::Incr_GL:
return VK_STENCIL_OP_INCREMENT_AND_WRAP;
- case Maxwell::StencilOp::DecrWrap:
- case Maxwell::StencilOp::DecrWrapOGL:
+ case Maxwell::StencilOp::Op::Decr_D3D:
+ case Maxwell::StencilOp::Op::Decr_GL:
return VK_STENCIL_OP_DECREMENT_AND_WRAP;
}
UNIMPLEMENTED_MSG("Unimplemented stencil op={}", stencil_op);
@@ -596,20 +617,20 @@ VkStencilOp StencilOp(Maxwell::StencilOp stencil_op) {
VkBlendOp BlendEquation(Maxwell::Blend::Equation equation) {
switch (equation) {
- case Maxwell::Blend::Equation::Add:
- case Maxwell::Blend::Equation::AddGL:
+ case Maxwell::Blend::Equation::Add_D3D:
+ case Maxwell::Blend::Equation::Add_GL:
return VK_BLEND_OP_ADD;
- case Maxwell::Blend::Equation::Subtract:
- case Maxwell::Blend::Equation::SubtractGL:
+ case Maxwell::Blend::Equation::Subtract_D3D:
+ case Maxwell::Blend::Equation::Subtract_GL:
return VK_BLEND_OP_SUBTRACT;
- case Maxwell::Blend::Equation::ReverseSubtract:
- case Maxwell::Blend::Equation::ReverseSubtractGL:
+ case Maxwell::Blend::Equation::ReverseSubtract_D3D:
+ case Maxwell::Blend::Equation::ReverseSubtract_GL:
return VK_BLEND_OP_REVERSE_SUBTRACT;
- case Maxwell::Blend::Equation::Min:
- case Maxwell::Blend::Equation::MinGL:
+ case Maxwell::Blend::Equation::Min_D3D:
+ case Maxwell::Blend::Equation::Min_GL:
return VK_BLEND_OP_MIN;
- case Maxwell::Blend::Equation::Max:
- case Maxwell::Blend::Equation::MaxGL:
+ case Maxwell::Blend::Equation::Max_D3D:
+ case Maxwell::Blend::Equation::Max_GL:
return VK_BLEND_OP_MAX;
}
UNIMPLEMENTED_MSG("Unimplemented blend equation={}", equation);
@@ -618,62 +639,62 @@ VkBlendOp BlendEquation(Maxwell::Blend::Equation equation) {
VkBlendFactor BlendFactor(Maxwell::Blend::Factor factor) {
switch (factor) {
- case Maxwell::Blend::Factor::Zero:
- case Maxwell::Blend::Factor::ZeroGL:
+ case Maxwell::Blend::Factor::Zero_D3D:
+ case Maxwell::Blend::Factor::Zero_GL:
return VK_BLEND_FACTOR_ZERO;
- case Maxwell::Blend::Factor::One:
- case Maxwell::Blend::Factor::OneGL:
+ case Maxwell::Blend::Factor::One_D3D:
+ case Maxwell::Blend::Factor::One_GL:
return VK_BLEND_FACTOR_ONE;
- case Maxwell::Blend::Factor::SourceColor:
- case Maxwell::Blend::Factor::SourceColorGL:
+ case Maxwell::Blend::Factor::SourceColor_D3D:
+ case Maxwell::Blend::Factor::SourceColor_GL:
return VK_BLEND_FACTOR_SRC_COLOR;
- case Maxwell::Blend::Factor::OneMinusSourceColor:
- case Maxwell::Blend::Factor::OneMinusSourceColorGL:
+ case Maxwell::Blend::Factor::OneMinusSourceColor_D3D:
+ case Maxwell::Blend::Factor::OneMinusSourceColor_GL:
return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
- case Maxwell::Blend::Factor::SourceAlpha:
- case Maxwell::Blend::Factor::SourceAlphaGL:
+ case Maxwell::Blend::Factor::SourceAlpha_D3D:
+ case Maxwell::Blend::Factor::SourceAlpha_GL:
return VK_BLEND_FACTOR_SRC_ALPHA;
- case Maxwell::Blend::Factor::OneMinusSourceAlpha:
- case Maxwell::Blend::Factor::OneMinusSourceAlphaGL:
+ case Maxwell::Blend::Factor::OneMinusSourceAlpha_D3D:
+ case Maxwell::Blend::Factor::OneMinusSourceAlpha_GL:
return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
- case Maxwell::Blend::Factor::DestAlpha:
- case Maxwell::Blend::Factor::DestAlphaGL:
+ case Maxwell::Blend::Factor::DestAlpha_D3D:
+ case Maxwell::Blend::Factor::DestAlpha_GL:
return VK_BLEND_FACTOR_DST_ALPHA;
- case Maxwell::Blend::Factor::OneMinusDestAlpha:
- case Maxwell::Blend::Factor::OneMinusDestAlphaGL:
+ case Maxwell::Blend::Factor::OneMinusDestAlpha_D3D:
+ case Maxwell::Blend::Factor::OneMinusDestAlpha_GL:
return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
- case Maxwell::Blend::Factor::DestColor:
- case Maxwell::Blend::Factor::DestColorGL:
+ case Maxwell::Blend::Factor::DestColor_D3D:
+ case Maxwell::Blend::Factor::DestColor_GL:
return VK_BLEND_FACTOR_DST_COLOR;
- case Maxwell::Blend::Factor::OneMinusDestColor:
- case Maxwell::Blend::Factor::OneMinusDestColorGL:
+ case Maxwell::Blend::Factor::OneMinusDestColor_D3D:
+ case Maxwell::Blend::Factor::OneMinusDestColor_GL:
return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
- case Maxwell::Blend::Factor::SourceAlphaSaturate:
- case Maxwell::Blend::Factor::SourceAlphaSaturateGL:
+ case Maxwell::Blend::Factor::SourceAlphaSaturate_D3D:
+ case Maxwell::Blend::Factor::SourceAlphaSaturate_GL:
return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
- case Maxwell::Blend::Factor::Source1Color:
- case Maxwell::Blend::Factor::Source1ColorGL:
+ case Maxwell::Blend::Factor::Source1Color_D3D:
+ case Maxwell::Blend::Factor::Source1Color_GL:
return VK_BLEND_FACTOR_SRC1_COLOR;
- case Maxwell::Blend::Factor::OneMinusSource1Color:
- case Maxwell::Blend::Factor::OneMinusSource1ColorGL:
+ case Maxwell::Blend::Factor::OneMinusSource1Color_D3D:
+ case Maxwell::Blend::Factor::OneMinusSource1Color_GL:
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
- case Maxwell::Blend::Factor::Source1Alpha:
- case Maxwell::Blend::Factor::Source1AlphaGL:
+ case Maxwell::Blend::Factor::Source1Alpha_D3D:
+ case Maxwell::Blend::Factor::Source1Alpha_GL:
return VK_BLEND_FACTOR_SRC1_ALPHA;
- case Maxwell::Blend::Factor::OneMinusSource1Alpha:
- case Maxwell::Blend::Factor::OneMinusSource1AlphaGL:
+ case Maxwell::Blend::Factor::OneMinusSource1Alpha_D3D:
+ case Maxwell::Blend::Factor::OneMinusSource1Alpha_GL:
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
- case Maxwell::Blend::Factor::ConstantColor:
- case Maxwell::Blend::Factor::ConstantColorGL:
+ case Maxwell::Blend::Factor::BlendFactor_D3D:
+ case Maxwell::Blend::Factor::ConstantColor_GL:
return VK_BLEND_FACTOR_CONSTANT_COLOR;
- case Maxwell::Blend::Factor::OneMinusConstantColor:
- case Maxwell::Blend::Factor::OneMinusConstantColorGL:
+ case Maxwell::Blend::Factor::OneMinusBlendFactor_D3D:
+ case Maxwell::Blend::Factor::OneMinusConstantColor_GL:
return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
- case Maxwell::Blend::Factor::ConstantAlpha:
- case Maxwell::Blend::Factor::ConstantAlphaGL:
+ case Maxwell::Blend::Factor::BothSourceAlpha_D3D:
+ case Maxwell::Blend::Factor::ConstantAlpha_GL:
return VK_BLEND_FACTOR_CONSTANT_ALPHA;
- case Maxwell::Blend::Factor::OneMinusConstantAlpha:
- case Maxwell::Blend::Factor::OneMinusConstantAlphaGL:
+ case Maxwell::Blend::Factor::OneMinusBothSourceAlpha_D3D:
+ case Maxwell::Blend::Factor::OneMinusConstantAlpha_GL:
return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
}
UNIMPLEMENTED_MSG("Unimplemented blend factor={}", factor);
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.h b/src/video_core/renderer_vulkan/maxwell_to_vk.h
index 356d46292..6f65502d6 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.h
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.h
@@ -55,7 +55,7 @@ VkCompareOp ComparisonOp(Maxwell::ComparisonOp comparison);
VkIndexType IndexFormat(Maxwell::IndexFormat index_format);
-VkStencilOp StencilOp(Maxwell::StencilOp stencil_op);
+VkStencilOp StencilOp(Maxwell::StencilOp::Op stencil_op);
VkBlendOp BlendEquation(Maxwell::Blend::Equation equation);
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index f47786f48..c3f66c8a3 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -288,7 +288,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
buffer_cache.SetUniformBuffersState(enabled_uniform_buffer_masks, &uniform_buffer_sizes);
const auto& regs{maxwell3d->regs};
- const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex};
+ const bool via_header_index{regs.sampler_binding == Maxwell::SamplerBinding::ViaHeaderBinding};
const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
const Shader::Info& info{stage_infos[stage]};
buffer_cache.UnbindGraphicsStorageBuffers(stage);
@@ -664,15 +664,6 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
.lineStippleFactor = 0,
.lineStipplePattern = 0,
};
- VkPipelineRasterizationConservativeStateCreateInfoEXT conservative_raster{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT,
- .pNext = nullptr,
- .flags = 0,
- .conservativeRasterizationMode = key.state.conservative_raster_enable != 0
- ? VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT
- : VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT,
- .extraPrimitiveOverestimationSize = 0.0f,
- };
VkPipelineRasterizationProvokingVertexStateCreateInfoEXT provoking_vertex{
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT,
.pNext = nullptr,
@@ -683,9 +674,6 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
if (IsLine(input_assembly_topology) && device.IsExtLineRasterizationSupported()) {
line_state.pNext = std::exchange(rasterization_ci.pNext, &line_state);
}
- if (device.IsExtConservativeRasterizationSupported()) {
- conservative_raster.pNext = std::exchange(rasterization_ci.pNext, &conservative_raster);
- }
if (device.IsExtProvokingVertexSupported()) {
provoking_vertex.pNext = std::exchange(rasterization_ci.pNext, &provoking_vertex);
}
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 732e7b6f2..20f1d6584 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -62,29 +62,29 @@ auto MakeSpan(Container& container) {
Shader::CompareFunction MaxwellToCompareFunction(Maxwell::ComparisonOp comparison) {
switch (comparison) {
- case Maxwell::ComparisonOp::Never:
- case Maxwell::ComparisonOp::NeverOld:
+ case Maxwell::ComparisonOp::Never_D3D:
+ case Maxwell::ComparisonOp::Never_GL:
return Shader::CompareFunction::Never;
- case Maxwell::ComparisonOp::Less:
- case Maxwell::ComparisonOp::LessOld:
+ case Maxwell::ComparisonOp::Less_D3D:
+ case Maxwell::ComparisonOp::Less_GL:
return Shader::CompareFunction::Less;
- case Maxwell::ComparisonOp::Equal:
- case Maxwell::ComparisonOp::EqualOld:
+ case Maxwell::ComparisonOp::Equal_D3D:
+ case Maxwell::ComparisonOp::Equal_GL:
return Shader::CompareFunction::Equal;
- case Maxwell::ComparisonOp::LessEqual:
- case Maxwell::ComparisonOp::LessEqualOld:
+ case Maxwell::ComparisonOp::LessEqual_D3D:
+ case Maxwell::ComparisonOp::LessEqual_GL:
return Shader::CompareFunction::LessThanEqual;
- case Maxwell::ComparisonOp::Greater:
- case Maxwell::ComparisonOp::GreaterOld:
+ case Maxwell::ComparisonOp::Greater_D3D:
+ case Maxwell::ComparisonOp::Greater_GL:
return Shader::CompareFunction::Greater;
- case Maxwell::ComparisonOp::NotEqual:
- case Maxwell::ComparisonOp::NotEqualOld:
+ case Maxwell::ComparisonOp::NotEqual_D3D:
+ case Maxwell::ComparisonOp::NotEqual_GL:
return Shader::CompareFunction::NotEqual;
- case Maxwell::ComparisonOp::GreaterEqual:
- case Maxwell::ComparisonOp::GreaterEqualOld:
+ case Maxwell::ComparisonOp::GreaterEqual_D3D:
+ case Maxwell::ComparisonOp::GreaterEqual_GL:
return Shader::CompareFunction::GreaterThanEqual;
- case Maxwell::ComparisonOp::Always:
- case Maxwell::ComparisonOp::AlwaysOld:
+ case Maxwell::ComparisonOp::Always_D3D:
+ case Maxwell::ComparisonOp::Always_GL:
return Shader::CompareFunction::Always;
}
UNIMPLEMENTED_MSG("Unimplemented comparison op={}", comparison);
@@ -96,15 +96,18 @@ Shader::AttributeType CastAttributeType(const FixedPipelineState::VertexAttribut
return Shader::AttributeType::Disabled;
}
switch (attr.Type()) {
- case Maxwell::VertexAttribute::Type::SignedNorm:
- case Maxwell::VertexAttribute::Type::UnsignedNorm:
- case Maxwell::VertexAttribute::Type::UnsignedScaled:
- case Maxwell::VertexAttribute::Type::SignedScaled:
+ case Maxwell::VertexAttribute::Type::UnusedEnumDoNotUseBecauseItWillGoAway:
+ ASSERT_MSG(false, "Invalid vertex attribute type!");
+ return Shader::AttributeType::Disabled;
+ case Maxwell::VertexAttribute::Type::SNorm:
+ case Maxwell::VertexAttribute::Type::UNorm:
+ case Maxwell::VertexAttribute::Type::UScaled:
+ case Maxwell::VertexAttribute::Type::SScaled:
case Maxwell::VertexAttribute::Type::Float:
return Shader::AttributeType::Float;
- case Maxwell::VertexAttribute::Type::SignedInt:
+ case Maxwell::VertexAttribute::Type::SInt:
return Shader::AttributeType::SignedInt;
- case Maxwell::VertexAttribute::Type::UnsignedInt:
+ case Maxwell::VertexAttribute::Type::UInt:
return Shader::AttributeType::UnsignedInt;
}
return Shader::AttributeType::Float;
@@ -162,16 +165,14 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
}
break;
case Shader::Stage::TessellationEval:
- // We have to flip tessellation clockwise for some reason...
- info.tess_clockwise = key.state.tessellation_clockwise == 0;
info.tess_primitive = [&key] {
const u32 raw{key.state.tessellation_primitive.Value()};
- switch (static_cast<Maxwell::TessellationPrimitive>(raw)) {
- case Maxwell::TessellationPrimitive::Isolines:
+ switch (static_cast<Maxwell::Tessellation::DomainType>(raw)) {
+ case Maxwell::Tessellation::DomainType::Isolines:
return Shader::TessPrimitive::Isolines;
- case Maxwell::TessellationPrimitive::Triangles:
+ case Maxwell::Tessellation::DomainType::Triangles:
return Shader::TessPrimitive::Triangles;
- case Maxwell::TessellationPrimitive::Quads:
+ case Maxwell::Tessellation::DomainType::Quads:
return Shader::TessPrimitive::Quads;
}
ASSERT(false);
@@ -179,12 +180,12 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
}();
info.tess_spacing = [&] {
const u32 raw{key.state.tessellation_spacing};
- switch (static_cast<Maxwell::TessellationSpacing>(raw)) {
- case Maxwell::TessellationSpacing::Equal:
+ switch (static_cast<Maxwell::Tessellation::Spacing>(raw)) {
+ case Maxwell::Tessellation::Spacing::Integer:
return Shader::TessSpacing::Equal;
- case Maxwell::TessellationSpacing::FractionalOdd:
+ case Maxwell::Tessellation::Spacing::FractionalOdd:
return Shader::TessSpacing::FractionalOdd;
- case Maxwell::TessellationSpacing::FractionalEven:
+ case Maxwell::Tessellation::Spacing::FractionalEven:
return Shader::TessSpacing::FractionalEven;
}
ASSERT(false);
@@ -490,7 +491,7 @@ GraphicsPipeline* PipelineCache::BuiltPipeline(GraphicsPipeline* pipeline) const
// If games are using a small index count, we can assume these are full screen quads.
// Usually these shaders are only used once for building textures so we can assume they
// can't be built async
- if (maxwell3d->regs.index_array.count <= 6 || maxwell3d->regs.vertex_buffer.count <= 6) {
+ if (maxwell3d->regs.index_buffer.count <= 6 || maxwell3d->regs.vertex_buffer.count <= 6) {
return pipeline;
}
return nullptr;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index acfd5da7d..47dfb45a1 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -70,7 +70,7 @@ VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t in
const float width = conv(src.scale_x * 2.0f);
float y = conv(src.translate_y - src.scale_y);
float height = conv(src.scale_y * 2.0f);
- bool y_negate = regs.screen_y_control.y_negate;
+ bool y_negate = regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft;
if (!device.IsNvViewportSwizzleSupported()) {
y_negate = y_negate != (src.swizzle.y == Maxwell::ViewportSwizzle::NegativeY);
@@ -130,11 +130,11 @@ VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u3
DrawParams MakeDrawParams(const Maxwell& regs, u32 num_instances, bool is_instanced,
bool is_indexed) {
DrawParams params{
- .base_instance = regs.vb_base_instance,
+ .base_instance = regs.global_base_instance_index,
.num_instances = is_instanced ? num_instances : 1,
- .base_vertex = is_indexed ? regs.vb_element_base : regs.vertex_buffer.first,
- .num_vertices = is_indexed ? regs.index_array.count : regs.vertex_buffer.count,
- .first_index = is_indexed ? regs.index_array.first : 0,
+ .base_vertex = is_indexed ? regs.global_base_vertex_index : regs.vertex_buffer.first,
+ .num_vertices = is_indexed ? regs.index_buffer.count : regs.vertex_buffer.count,
+ .first_index = is_indexed ? regs.index_buffer.first : 0,
.is_indexed = is_indexed,
};
if (regs.draw.topology == Maxwell::PrimitiveTopology::Quads) {
@@ -225,10 +225,10 @@ void RasterizerVulkan::Clear() {
query_cache.UpdateCounters();
auto& regs = maxwell3d->regs;
- const bool use_color = regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
- regs.clear_buffers.A;
- const bool use_depth = regs.clear_buffers.Z;
- const bool use_stencil = regs.clear_buffers.S;
+ const bool use_color = regs.clear_surface.R || regs.clear_surface.G || regs.clear_surface.B ||
+ regs.clear_surface.A;
+ const bool use_depth = regs.clear_surface.Z;
+ const bool use_stencil = regs.clear_surface.S;
if (!use_color && !use_depth && !use_stencil) {
return;
}
@@ -254,9 +254,9 @@ void RasterizerVulkan::Clear() {
default_scissor.extent.height = std::numeric_limits<s32>::max();
VkClearRect clear_rect{
- .rect = regs.clear_flags.scissor ? GetScissorState(regs, 0, up_scale, down_shift)
- : default_scissor,
- .baseArrayLayer = regs.clear_buffers.layer,
+ .rect = regs.clear_control.use_scissor ? GetScissorState(regs, 0, up_scale, down_shift)
+ : default_scissor,
+ .baseArrayLayer = regs.clear_surface.layer,
.layerCount = 1,
};
if (clear_rect.rect.extent.width == 0 || clear_rect.rect.extent.height == 0) {
@@ -267,7 +267,7 @@ void RasterizerVulkan::Clear() {
.height = std::min(clear_rect.rect.extent.height, render_area.height),
};
- const u32 color_attachment = regs.clear_buffers.RT;
+ const u32 color_attachment = regs.clear_surface.RT;
if (use_color && framebuffer->HasAspectColorBit(color_attachment)) {
VkClearValue clear_value;
bool is_integer = false;
@@ -289,7 +289,8 @@ void RasterizerVulkan::Clear() {
break;
}
if (!is_integer) {
- std::memcpy(clear_value.color.float32, regs.clear_color, sizeof(regs.clear_color));
+ std::memcpy(clear_value.color.float32, regs.clear_color.data(),
+ regs.clear_color.size() * sizeof(f32));
} else if (!is_signed) {
for (size_t i = 0; i < 4; i++) {
clear_value.color.uint32[i] = static_cast<u32>(
@@ -648,23 +649,23 @@ void RasterizerVulkan::UpdateDynamicStates() {
void RasterizerVulkan::BeginTransformFeedback() {
const auto& regs = maxwell3d->regs;
- if (regs.tfb_enabled == 0) {
+ if (regs.transform_feedback_enabled == 0) {
return;
}
if (!device.IsExtTransformFeedbackSupported()) {
LOG_ERROR(Render_Vulkan, "Transform feedbacks used but not supported");
return;
}
- UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationControl) ||
- regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationEval) ||
- regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::Geometry));
+ UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderType::TessellationInit) ||
+ regs.IsShaderConfigEnabled(Maxwell::ShaderType::Tessellation) ||
+ regs.IsShaderConfigEnabled(Maxwell::ShaderType::Geometry));
scheduler.Record(
[](vk::CommandBuffer cmdbuf) { cmdbuf.BeginTransformFeedbackEXT(0, 0, nullptr, nullptr); });
}
void RasterizerVulkan::EndTransformFeedback() {
const auto& regs = maxwell3d->regs;
- if (regs.tfb_enabled == 0) {
+ if (regs.transform_feedback_enabled == 0) {
return;
}
if (!device.IsExtTransformFeedbackSupported()) {
@@ -728,11 +729,11 @@ void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchDepthBias()) {
return;
}
- float units = regs.polygon_offset_units / 2.0f;
- const bool is_d24 = regs.zeta.format == Tegra::DepthFormat::S8_UINT_Z24_UNORM ||
- regs.zeta.format == Tegra::DepthFormat::D24X8_UNORM ||
- regs.zeta.format == Tegra::DepthFormat::D24S8_UNORM ||
- regs.zeta.format == Tegra::DepthFormat::D24C8_UNORM;
+ float units = regs.depth_bias / 2.0f;
+ const bool is_d24 = regs.zeta.format == Tegra::DepthFormat::Z24_UNORM_S8_UINT ||
+ regs.zeta.format == Tegra::DepthFormat::X8Z24_UNORM ||
+ regs.zeta.format == Tegra::DepthFormat::S8Z24_UNORM ||
+ regs.zeta.format == Tegra::DepthFormat::V8Z24_UNORM;
if (is_d24 && !device.SupportsD24DepthBuffer()) {
// the base formulas can be obtained from here:
// https://docs.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-output-merger-stage-depth-bias
@@ -740,8 +741,8 @@ void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) {
static_cast<double>(1ULL << (32 - 24)) / (static_cast<double>(0x1.ep+127));
units = static_cast<float>(static_cast<double>(units) * rescale_factor);
}
- scheduler.Record([constant = units, clamp = regs.polygon_offset_clamp,
- factor = regs.polygon_offset_factor](vk::CommandBuffer cmdbuf) {
+ scheduler.Record([constant = units, clamp = regs.depth_bias_clamp,
+ factor = regs.slope_scale_depth_bias](vk::CommandBuffer cmdbuf) {
cmdbuf.SetDepthBias(constant, clamp, factor);
});
}
@@ -771,8 +772,8 @@ void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs)
if (regs.stencil_two_side_enable) {
// Separate values per face
scheduler.Record(
- [front_ref = regs.stencil_front_func_ref, front_write_mask = regs.stencil_front_mask,
- front_test_mask = regs.stencil_front_func_mask, back_ref = regs.stencil_back_func_ref,
+ [front_ref = regs.stencil_front_ref, front_write_mask = regs.stencil_front_mask,
+ front_test_mask = regs.stencil_front_func_mask, back_ref = regs.stencil_back_ref,
back_write_mask = regs.stencil_back_mask,
back_test_mask = regs.stencil_back_func_mask](vk::CommandBuffer cmdbuf) {
// Front face
@@ -787,7 +788,7 @@ void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs)
});
} else {
// Front face defines both faces
- scheduler.Record([ref = regs.stencil_front_func_ref, write_mask = regs.stencil_front_mask,
+ scheduler.Record([ref = regs.stencil_front_ref, write_mask = regs.stencil_front_mask,
test_mask = regs.stencil_front_func_mask](vk::CommandBuffer cmdbuf) {
cmdbuf.SetStencilReference(VK_STENCIL_FACE_FRONT_AND_BACK, ref);
cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_FRONT_AND_BACK, write_mask);
@@ -800,7 +801,8 @@ void RasterizerVulkan::UpdateLineWidth(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchLineWidth()) {
return;
}
- const float width = regs.line_smooth_enable ? regs.line_width_smooth : regs.line_width_aliased;
+ const float width =
+ regs.line_anti_alias_enable ? regs.line_width_smooth : regs.line_width_aliased;
scheduler.Record([width](vk::CommandBuffer cmdbuf) { cmdbuf.SetLineWidth(width); });
}
@@ -808,10 +810,10 @@ void RasterizerVulkan::UpdateCullMode(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchCullMode()) {
return;
}
- scheduler.Record(
- [enabled = regs.cull_test_enabled, cull_face = regs.cull_face](vk::CommandBuffer cmdbuf) {
- cmdbuf.SetCullModeEXT(enabled ? MaxwellToVK::CullFace(cull_face) : VK_CULL_MODE_NONE);
- });
+ scheduler.Record([enabled = regs.gl_cull_test_enabled,
+ cull_face = regs.gl_cull_face](vk::CommandBuffer cmdbuf) {
+ cmdbuf.SetCullModeEXT(enabled ? MaxwellToVK::CullFace(cull_face) : VK_CULL_MODE_NONE);
+ });
}
void RasterizerVulkan::UpdateDepthBoundsTestEnable(Tegra::Engines::Maxwell3D::Regs& regs) {
@@ -860,8 +862,8 @@ void RasterizerVulkan::UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs) {
return;
}
- VkFrontFace front_face = MaxwellToVK::FrontFace(regs.front_face);
- if (regs.screen_y_control.triangle_rast_flip != 0) {
+ VkFrontFace front_face = MaxwellToVK::FrontFace(regs.gl_front_face);
+ if (regs.window_origin.flip_y != 0) {
front_face = front_face == VK_FRONT_FACE_CLOCKWISE ? VK_FRONT_FACE_COUNTER_CLOCKWISE
: VK_FRONT_FACE_CLOCKWISE;
}
@@ -873,16 +875,16 @@ void RasterizerVulkan::UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchStencilOp()) {
return;
}
- const Maxwell::StencilOp fail = regs.stencil_front_op_fail;
- const Maxwell::StencilOp zfail = regs.stencil_front_op_zfail;
- const Maxwell::StencilOp zpass = regs.stencil_front_op_zpass;
- const Maxwell::ComparisonOp compare = regs.stencil_front_func_func;
+ const Maxwell::StencilOp::Op fail = regs.stencil_front_op.fail;
+ const Maxwell::StencilOp::Op zfail = regs.stencil_front_op.zfail;
+ const Maxwell::StencilOp::Op zpass = regs.stencil_front_op.zpass;
+ const Maxwell::ComparisonOp compare = regs.stencil_front_op.func;
if (regs.stencil_two_side_enable) {
// Separate stencil op per face
- const Maxwell::StencilOp back_fail = regs.stencil_back_op_fail;
- const Maxwell::StencilOp back_zfail = regs.stencil_back_op_zfail;
- const Maxwell::StencilOp back_zpass = regs.stencil_back_op_zpass;
- const Maxwell::ComparisonOp back_compare = regs.stencil_back_func_func;
+ const Maxwell::StencilOp::Op back_fail = regs.stencil_back_op.fail;
+ const Maxwell::StencilOp::Op back_zfail = regs.stencil_back_op.zfail;
+ const Maxwell::StencilOp::Op back_zpass = regs.stencil_back_op.zpass;
+ const Maxwell::ComparisonOp back_compare = regs.stencil_back_op.func;
scheduler.Record([fail, zfail, zpass, compare, back_fail, back_zfail, back_zpass,
back_compare](vk::CommandBuffer cmdbuf) {
cmdbuf.SetStencilOpEXT(VK_STENCIL_FACE_FRONT_BIT, MaxwellToVK::StencilOp(fail),
@@ -954,15 +956,15 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs)
dirty[Dirty::VertexBinding0 + index] = false;
const u32 binding{static_cast<u32>(index)};
- const auto& input_binding{regs.vertex_array[binding]};
- const bool is_instanced{regs.instanced_arrays.IsInstancingEnabled(binding)};
+ const auto& input_binding{regs.vertex_streams[binding]};
+ const bool is_instanced{regs.vertex_stream_instances.IsInstancingEnabled(binding)};
bindings.push_back({
.sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT,
.pNext = nullptr,
.binding = binding,
.stride = input_binding.stride,
.inputRate = is_instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX,
- .divisor = is_instanced ? input_binding.divisor : 1,
+ .divisor = is_instanced ? input_binding.frequency : 1,
});
}
scheduler.Record([bindings, attributes](vk::CommandBuffer cmdbuf) {
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp
index d96720b80..7934f2a51 100644
--- a/src/video_core/renderer_vulkan/vk_scheduler.cpp
+++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp
@@ -139,6 +139,7 @@ void Scheduler::WorkerThread(std::stop_token stop_token) {
Common::SetCurrentThreadName("VulkanWorker");
do {
std::unique_ptr<CommandChunk> work;
+ bool has_submit{false};
{
std::unique_lock lock{work_mutex};
if (work_queue.empty()) {
@@ -150,9 +151,10 @@ void Scheduler::WorkerThread(std::stop_token stop_token) {
}
work = std::move(work_queue.front());
work_queue.pop();
+
+ has_submit = work->HasSubmit();
+ work->ExecuteAll(current_cmdbuf);
}
- const bool has_submit = work->HasSubmit();
- work->ExecuteAll(current_cmdbuf);
if (has_submit) {
AllocateWorkerCommandBuffer();
}
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
index 7fb256953..06f68d09a 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
@@ -26,39 +26,20 @@ using namespace Common::Literals;
constexpr VkDeviceSize MAX_ALIGNMENT = 256;
// Maximum size to put elements in the stream buffer
constexpr VkDeviceSize MAX_STREAM_BUFFER_REQUEST_SIZE = 8_MiB;
+// Stream buffer size in bytes
+constexpr VkDeviceSize STREAM_BUFFER_SIZE = 128_MiB;
+constexpr VkDeviceSize REGION_SIZE = STREAM_BUFFER_SIZE / StagingBufferPool::NUM_SYNCS;
constexpr VkMemoryPropertyFlags HOST_FLAGS =
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
constexpr VkMemoryPropertyFlags STREAM_FLAGS = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | HOST_FLAGS;
-static bool IsStreamHeap(VkMemoryHeap heap, size_t staging_buffer_size) noexcept {
- return staging_buffer_size < (heap.size * 2) / 3;
-}
-
-static bool HasLargeDeviceLocalHostVisibleMemory(const VkPhysicalDeviceMemoryProperties& props) {
- const auto flags{VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT};
-
- for (u32 type_index = 0; type_index < props.memoryTypeCount; ++type_index) {
- const auto& memory_type{props.memoryTypes[type_index]};
-
- if ((memory_type.propertyFlags & flags) != flags) {
- // Memory must be device local and host visible
- continue;
- }
-
- const auto& heap{props.memoryHeaps[memory_type.heapIndex]};
- if (heap.size >= 7168_MiB) {
- // This is the right type of memory
- return true;
- }
- }
-
- return false;
+bool IsStreamHeap(VkMemoryHeap heap) noexcept {
+ return STREAM_BUFFER_SIZE < (heap.size * 2) / 3;
}
std::optional<u32> FindMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& props, u32 type_mask,
- VkMemoryPropertyFlags flags,
- size_t staging_buffer_size) noexcept {
+ VkMemoryPropertyFlags flags) noexcept {
for (u32 type_index = 0; type_index < props.memoryTypeCount; ++type_index) {
if (((type_mask >> type_index) & 1) == 0) {
// Memory type is incompatible
@@ -69,7 +50,7 @@ std::optional<u32> FindMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& p
// Memory type doesn't have the flags we want
continue;
}
- if (!IsStreamHeap(props.memoryHeaps[memory_type.heapIndex], staging_buffer_size)) {
+ if (!IsStreamHeap(props.memoryHeaps[memory_type.heapIndex])) {
// Memory heap is not suitable for streaming
continue;
}
@@ -80,17 +61,17 @@ std::optional<u32> FindMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& p
}
u32 FindMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& props, u32 type_mask,
- bool try_device_local, size_t staging_buffer_size) {
+ bool try_device_local) {
std::optional<u32> type;
if (try_device_local) {
// Try to find a DEVICE_LOCAL_BIT type, Nvidia and AMD have a dedicated heap for this
- type = FindMemoryTypeIndex(props, type_mask, STREAM_FLAGS, staging_buffer_size);
+ type = FindMemoryTypeIndex(props, type_mask, STREAM_FLAGS);
if (type) {
return *type;
}
}
// Otherwise try without the DEVICE_LOCAL_BIT
- type = FindMemoryTypeIndex(props, type_mask, HOST_FLAGS, staging_buffer_size);
+ type = FindMemoryTypeIndex(props, type_mask, HOST_FLAGS);
if (type) {
return *type;
}
@@ -98,32 +79,20 @@ u32 FindMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& props, u32 type_
throw vk::Exception(VK_ERROR_OUT_OF_DEVICE_MEMORY);
}
-size_t Region(size_t iterator, size_t region_size) noexcept {
- return iterator / region_size;
+size_t Region(size_t iterator) noexcept {
+ return iterator / REGION_SIZE;
}
} // Anonymous namespace
StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_,
Scheduler& scheduler_)
: device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_} {
-
- const auto memory_properties{device.GetPhysical().GetMemoryProperties().memoryProperties};
- if (HasLargeDeviceLocalHostVisibleMemory(memory_properties)) {
- // Possible on many integrated and newer discrete cards
- staging_buffer_size = 1_GiB;
- } else {
- // Well-supported default size used by most Vulkan PC games
- staging_buffer_size = 256_MiB;
- }
-
- region_size = staging_buffer_size / StagingBufferPool::NUM_SYNCS;
-
const vk::Device& dev = device.GetLogical();
stream_buffer = dev.CreateBuffer(VkBufferCreateInfo{
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
- .size = staging_buffer_size,
+ .size = STREAM_BUFFER_SIZE,
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
@@ -148,18 +117,19 @@ StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& mem
.image = nullptr,
.buffer = *stream_buffer,
};
+ const auto memory_properties = device.GetPhysical().GetMemoryProperties().memoryProperties;
VkMemoryAllocateInfo stream_memory_info{
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = make_dedicated ? &dedicated_info : nullptr,
.allocationSize = requirements.size,
- .memoryTypeIndex = FindMemoryTypeIndex(memory_properties, requirements.memoryTypeBits, true,
- staging_buffer_size),
+ .memoryTypeIndex =
+ FindMemoryTypeIndex(memory_properties, requirements.memoryTypeBits, true),
};
stream_memory = dev.TryAllocateMemory(stream_memory_info);
if (!stream_memory) {
LOG_INFO(Render_Vulkan, "Dynamic memory allocation failed, trying with system memory");
- stream_memory_info.memoryTypeIndex = FindMemoryTypeIndex(
- memory_properties, requirements.memoryTypeBits, false, staging_buffer_size);
+ stream_memory_info.memoryTypeIndex =
+ FindMemoryTypeIndex(memory_properties, requirements.memoryTypeBits, false);
stream_memory = dev.AllocateMemory(stream_memory_info);
}
@@ -167,7 +137,7 @@ StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& mem
stream_memory.SetObjectNameEXT("Stream Buffer Memory");
}
stream_buffer.BindMemory(*stream_memory, 0);
- stream_pointer = stream_memory.Map(0, staging_buffer_size);
+ stream_pointer = stream_memory.Map(0, STREAM_BUFFER_SIZE);
}
StagingBufferPool::~StagingBufferPool() = default;
@@ -188,25 +158,25 @@ void StagingBufferPool::TickFrame() {
}
StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) {
- if (AreRegionsActive(Region(free_iterator, region_size) + 1,
- std::min(Region(iterator + size, region_size) + 1, NUM_SYNCS))) {
+ if (AreRegionsActive(Region(free_iterator) + 1,
+ std::min(Region(iterator + size) + 1, NUM_SYNCS))) {
// Avoid waiting for the previous usages to be free
return GetStagingBuffer(size, MemoryUsage::Upload);
}
const u64 current_tick = scheduler.CurrentTick();
- std::fill(sync_ticks.begin() + Region(used_iterator, region_size),
- sync_ticks.begin() + Region(iterator, region_size), current_tick);
+ std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + Region(iterator),
+ current_tick);
used_iterator = iterator;
free_iterator = std::max(free_iterator, iterator + size);
- if (iterator + size >= staging_buffer_size) {
- std::fill(sync_ticks.begin() + Region(used_iterator, region_size),
- sync_ticks.begin() + NUM_SYNCS, current_tick);
+ if (iterator + size >= STREAM_BUFFER_SIZE) {
+ std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + NUM_SYNCS,
+ current_tick);
used_iterator = 0;
iterator = 0;
free_iterator = size;
- if (AreRegionsActive(0, Region(size, region_size) + 1)) {
+ if (AreRegionsActive(0, Region(size) + 1)) {
// Avoid waiting for the previous usages to be free
return GetStagingBuffer(size, MemoryUsage::Upload);
}
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
index 90c67177f..91dc84da8 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
@@ -93,9 +93,6 @@ private:
size_t free_iterator = 0;
std::array<u64, NUM_SYNCS> sync_ticks{};
- size_t staging_buffer_size = 0;
- size_t region_size = 0;
-
StagingBuffersCache device_local_cache;
StagingBuffersCache upload_cache;
StagingBuffersCache download_cache;
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
index f234e1a31..b87c3be66 100644
--- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp
+++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
@@ -51,8 +51,8 @@ Flags MakeInvalidationFlags() {
void SetupDirtyViewports(Tables& tables) {
FillBlock(tables[0], OFF(viewport_transform), NUM(viewport_transform), Viewports);
FillBlock(tables[0], OFF(viewports), NUM(viewports), Viewports);
- tables[0][OFF(viewport_transform_enabled)] = Viewports;
- tables[1][OFF(screen_y_control)] = Viewports;
+ tables[0][OFF(viewport_scale_offset_enbled)] = Viewports;
+ tables[1][OFF(window_origin)] = Viewports;
}
void SetupDirtyScissors(Tables& tables) {
@@ -61,9 +61,9 @@ void SetupDirtyScissors(Tables& tables) {
void SetupDirtyDepthBias(Tables& tables) {
auto& table = tables[0];
- table[OFF(polygon_offset_units)] = DepthBias;
- table[OFF(polygon_offset_clamp)] = DepthBias;
- table[OFF(polygon_offset_factor)] = DepthBias;
+ table[OFF(depth_bias)] = DepthBias;
+ table[OFF(depth_bias_clamp)] = DepthBias;
+ table[OFF(slope_scale_depth_bias)] = DepthBias;
}
void SetupDirtyBlendConstants(Tables& tables) {
@@ -77,10 +77,10 @@ void SetupDirtyDepthBounds(Tables& tables) {
void SetupDirtyStencilProperties(Tables& tables) {
auto& table = tables[0];
table[OFF(stencil_two_side_enable)] = StencilProperties;
- table[OFF(stencil_front_func_ref)] = StencilProperties;
+ table[OFF(stencil_front_ref)] = StencilProperties;
table[OFF(stencil_front_mask)] = StencilProperties;
table[OFF(stencil_front_func_mask)] = StencilProperties;
- table[OFF(stencil_back_func_ref)] = StencilProperties;
+ table[OFF(stencil_back_ref)] = StencilProperties;
table[OFF(stencil_back_mask)] = StencilProperties;
table[OFF(stencil_back_func_mask)] = StencilProperties;
}
@@ -92,8 +92,8 @@ void SetupDirtyLineWidth(Tables& tables) {
void SetupDirtyCullMode(Tables& tables) {
auto& table = tables[0];
- table[OFF(cull_face)] = CullMode;
- table[OFF(cull_test_enabled)] = CullMode;
+ table[OFF(gl_cull_face)] = CullMode;
+ table[OFF(gl_cull_test_enabled)] = CullMode;
}
void SetupDirtyDepthBoundsEnable(Tables& tables) {
@@ -114,20 +114,20 @@ void SetupDirtyDepthCompareOp(Tables& tables) {
void SetupDirtyFrontFace(Tables& tables) {
auto& table = tables[0];
- table[OFF(front_face)] = FrontFace;
- table[OFF(screen_y_control)] = FrontFace;
+ table[OFF(gl_front_face)] = FrontFace;
+ table[OFF(window_origin)] = FrontFace;
}
void SetupDirtyStencilOp(Tables& tables) {
auto& table = tables[0];
- table[OFF(stencil_front_op_fail)] = StencilOp;
- table[OFF(stencil_front_op_zfail)] = StencilOp;
- table[OFF(stencil_front_op_zpass)] = StencilOp;
- table[OFF(stencil_front_func_func)] = StencilOp;
- table[OFF(stencil_back_op_fail)] = StencilOp;
- table[OFF(stencil_back_op_zfail)] = StencilOp;
- table[OFF(stencil_back_op_zpass)] = StencilOp;
- table[OFF(stencil_back_func_func)] = StencilOp;
+ table[OFF(stencil_front_op.fail)] = StencilOp;
+ table[OFF(stencil_front_op.zfail)] = StencilOp;
+ table[OFF(stencil_front_op.zpass)] = StencilOp;
+ table[OFF(stencil_front_op.func)] = StencilOp;
+ table[OFF(stencil_back_op.fail)] = StencilOp;
+ table[OFF(stencil_back_op.zfail)] = StencilOp;
+ table[OFF(stencil_back_op.zpass)] = StencilOp;
+ table[OFF(stencil_back_op.func)] = StencilOp;
// Table 0 is used by StencilProperties
tables[1][OFF(stencil_two_side_enable)] = StencilOp;
@@ -139,10 +139,10 @@ void SetupDirtyStencilTestEnable(Tables& tables) {
void SetupDirtyBlending(Tables& tables) {
tables[0][OFF(color_mask_common)] = Blending;
- tables[0][OFF(independent_blend_enable)] = Blending;
+ tables[0][OFF(blend_per_target_enabled)] = Blending;
FillBlock(tables[0], OFF(color_mask), NUM(color_mask), Blending);
FillBlock(tables[0], OFF(blend), NUM(blend), Blending);
- FillBlock(tables[0], OFF(independent_blend), NUM(independent_blend), Blending);
+ FillBlock(tables[0], OFF(blend_per_target), NUM(blend_per_target), Blending);
}
void SetupDirtyViewportSwizzles(Tables& tables) {
@@ -166,10 +166,10 @@ void SetupDirtyVertexBindings(Tables& tables) {
static constexpr size_t divisor_offset = 3;
for (size_t i = 0; i < Regs::NumVertexArrays; ++i) {
const u8 flag = static_cast<u8>(VertexBinding0 + i);
- tables[0][OFF(instanced_arrays) + i] = VertexInput;
- tables[1][OFF(instanced_arrays) + i] = flag;
- tables[0][OFF(vertex_array) + i * NUM(vertex_array[0]) + divisor_offset] = VertexInput;
- tables[1][OFF(vertex_array) + i * NUM(vertex_array[0]) + divisor_offset] = flag;
+ tables[0][OFF(vertex_stream_instances) + i] = VertexInput;
+ tables[1][OFF(vertex_stream_instances) + i] = flag;
+ tables[0][OFF(vertex_streams) + i * NUM(vertex_streams[0]) + divisor_offset] = VertexInput;
+ tables[1][OFF(vertex_streams) + i * NUM(vertex_streams[0]) + divisor_offset] = flag;
}
}
} // Anonymous namespace
diff --git a/src/video_core/shader_cache.cpp b/src/video_core/shader_cache.cpp
index f53066579..d9482371b 100644
--- a/src/video_core/shader_cache.cpp
+++ b/src/video_core/shader_cache.cpp
@@ -43,14 +43,14 @@ bool ShaderCache::RefreshStages(std::array<u64, 6>& unique_hashes) {
}
dirty[VideoCommon::Dirty::Shaders] = false;
- const GPUVAddr base_addr{maxwell3d->regs.code_address.CodeAddress()};
+ const GPUVAddr base_addr{maxwell3d->regs.program_region.Address()};
for (size_t index = 0; index < Tegra::Engines::Maxwell3D::Regs::MaxShaderProgram; ++index) {
if (!maxwell3d->regs.IsShaderConfigEnabled(index)) {
unique_hashes[index] = 0;
continue;
}
- const auto& shader_config{maxwell3d->regs.shader_config[index]};
- const auto program{static_cast<Tegra::Engines::Maxwell3D::Regs::ShaderProgram>(index)};
+ const auto& shader_config{maxwell3d->regs.pipelines[index]};
+ const auto program{static_cast<Tegra::Engines::Maxwell3D::Regs::ShaderType>(index)};
const GPUVAddr shader_addr{base_addr + shader_config.offset};
const std::optional<VAddr> cpu_shader_addr{gpu_memory->GpuToCpuAddress(shader_addr)};
if (!cpu_shader_addr) {
@@ -90,14 +90,14 @@ const ShaderInfo* ShaderCache::ComputeShader() {
void ShaderCache::GetGraphicsEnvironments(GraphicsEnvironments& result,
const std::array<u64, NUM_PROGRAMS>& unique_hashes) {
size_t env_index{};
- const GPUVAddr base_addr{maxwell3d->regs.code_address.CodeAddress()};
+ const GPUVAddr base_addr{maxwell3d->regs.program_region.Address()};
for (size_t index = 0; index < NUM_PROGRAMS; ++index) {
if (unique_hashes[index] == 0) {
continue;
}
- const auto program{static_cast<Tegra::Engines::Maxwell3D::Regs::ShaderProgram>(index)};
+ const auto program{static_cast<Tegra::Engines::Maxwell3D::Regs::ShaderType>(index)};
auto& env{result.envs[index]};
- const u32 start_address{maxwell3d->regs.shader_config[index].offset};
+ const u32 start_address{maxwell3d->regs.pipelines[index].offset};
env = GraphicsEnvironment{*maxwell3d, *gpu_memory, program, base_addr, start_address};
env.SetCachedSize(shader_infos[index]->size_bytes);
result.env_ptrs[env_index++] = &env;
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp
index 5f7625947..fbabb3219 100644
--- a/src/video_core/shader_environment.cpp
+++ b/src/video_core/shader_environment.cpp
@@ -250,34 +250,34 @@ Shader::TextureType GenericEnvironment::ReadTextureTypeImpl(GPUVAddr tic_addr, u
GraphicsEnvironment::GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_,
Tegra::MemoryManager& gpu_memory_,
- Maxwell::ShaderProgram program, GPUVAddr program_base_,
+ Maxwell::ShaderType program, GPUVAddr program_base_,
u32 start_address_)
: GenericEnvironment{gpu_memory_, program_base_, start_address_}, maxwell3d{&maxwell3d_} {
gpu_memory->ReadBlock(program_base + start_address, &sph, sizeof(sph));
initial_offset = sizeof(sph);
- gp_passthrough_mask = maxwell3d->regs.gp_passthrough_mask;
+ gp_passthrough_mask = maxwell3d->regs.post_vtg_shader_attrib_skip_mask;
switch (program) {
- case Maxwell::ShaderProgram::VertexA:
+ case Maxwell::ShaderType::VertexA:
stage = Shader::Stage::VertexA;
stage_index = 0;
break;
- case Maxwell::ShaderProgram::VertexB:
+ case Maxwell::ShaderType::VertexB:
stage = Shader::Stage::VertexB;
stage_index = 0;
break;
- case Maxwell::ShaderProgram::TesselationControl:
+ case Maxwell::ShaderType::TessellationInit:
stage = Shader::Stage::TessellationControl;
stage_index = 1;
break;
- case Maxwell::ShaderProgram::TesselationEval:
+ case Maxwell::ShaderType::Tessellation:
stage = Shader::Stage::TessellationEval;
stage_index = 2;
break;
- case Maxwell::ShaderProgram::Geometry:
+ case Maxwell::ShaderType::Geometry:
stage = Shader::Stage::Geometry;
stage_index = 3;
break;
- case Maxwell::ShaderProgram::Fragment:
+ case Maxwell::ShaderType::Pixel:
stage = Shader::Stage::Fragment;
stage_index = 4;
break;
@@ -288,7 +288,7 @@ GraphicsEnvironment::GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_,
const u64 local_size{sph.LocalMemorySize()};
ASSERT(local_size <= std::numeric_limits<u32>::max());
local_memory_size = static_cast<u32>(local_size) + sph.common3.shader_local_memory_crs_size;
- texture_bound = maxwell3d->regs.tex_cb_index;
+ texture_bound = maxwell3d->regs.bindless_texture_const_buffer_slot;
}
u32 GraphicsEnvironment::ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) {
@@ -304,8 +304,9 @@ u32 GraphicsEnvironment::ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) {
Shader::TextureType GraphicsEnvironment::ReadTextureType(u32 handle) {
const auto& regs{maxwell3d->regs};
- const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex};
- return ReadTextureTypeImpl(regs.tic.Address(), regs.tic.limit, via_header_index, handle);
+ const bool via_header_index{regs.sampler_binding == Maxwell::SamplerBinding::ViaHeaderBinding};
+ return ReadTextureTypeImpl(regs.tex_header.Address(), regs.tex_header.limit, via_header_index,
+ handle);
}
ComputeEnvironment::ComputeEnvironment(Tegra::Engines::KeplerCompute& kepler_compute_,
diff --git a/src/video_core/shader_environment.h b/src/video_core/shader_environment.h
index 5a145f33a..8b3b8e9f5 100644
--- a/src/video_core/shader_environment.h
+++ b/src/video_core/shader_environment.h
@@ -93,7 +93,7 @@ public:
explicit GraphicsEnvironment() = default;
explicit GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_,
Tegra::MemoryManager& gpu_memory_,
- Tegra::Engines::Maxwell3D::Regs::ShaderProgram program,
+ Tegra::Engines::Maxwell3D::Regs::ShaderType program,
GPUVAddr program_base_, u32 start_address_);
~GraphicsEnvironment() override = default;
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp
index a2bf08294..6bd133d10 100644
--- a/src/video_core/surface.cpp
+++ b/src/video_core/surface.cpp
@@ -73,17 +73,17 @@ bool SurfaceTargetIsArray(SurfaceTarget target) {
PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) {
switch (format) {
- case Tegra::DepthFormat::S8_UINT_Z24_UNORM:
+ case Tegra::DepthFormat::Z24_UNORM_S8_UINT:
return PixelFormat::S8_UINT_D24_UNORM;
- case Tegra::DepthFormat::D24S8_UNORM:
+ case Tegra::DepthFormat::S8Z24_UNORM:
return PixelFormat::D24_UNORM_S8_UINT;
- case Tegra::DepthFormat::D32_FLOAT:
+ case Tegra::DepthFormat::Z32_FLOAT:
return PixelFormat::D32_FLOAT;
- case Tegra::DepthFormat::D16_UNORM:
+ case Tegra::DepthFormat::Z16_UNORM:
return PixelFormat::D16_UNORM;
case Tegra::DepthFormat::S8_UINT:
return PixelFormat::S8_UINT;
- case Tegra::DepthFormat::D32_FLOAT_S8X24_UINT:
+ case Tegra::DepthFormat::Z32_FLOAT_X24S8_UINT:
return PixelFormat::D32_FLOAT_S8_UINT;
default:
UNIMPLEMENTED_MSG("Unimplemented format={}", format);
@@ -117,9 +117,9 @@ PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format)
return PixelFormat::R32G32_UINT;
case Tegra::RenderTargetFormat::R16G16B16X16_FLOAT:
return PixelFormat::R16G16B16X16_FLOAT;
- case Tegra::RenderTargetFormat::B8G8R8A8_UNORM:
+ case Tegra::RenderTargetFormat::A8R8G8B8_UNORM:
return PixelFormat::B8G8R8A8_UNORM;
- case Tegra::RenderTargetFormat::B8G8R8A8_SRGB:
+ case Tegra::RenderTargetFormat::A8R8G8B8_SRGB:
return PixelFormat::B8G8R8A8_SRGB;
case Tegra::RenderTargetFormat::A2B10G10R10_UNORM:
return PixelFormat::A2B10G10R10_UNORM;
diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp
index 6c073ee57..852ec2519 100644
--- a/src/video_core/texture_cache/image_info.cpp
+++ b/src/video_core/texture_cache/image_info.cpp
@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include <fmt/format.h>
+
#include "common/assert.h"
#include "video_core/surface.h"
#include "video_core/texture_cache/format_lookup_table.h"
@@ -12,6 +14,7 @@
namespace VideoCommon {
+using Tegra::Engines::Maxwell3D;
using Tegra::Texture::TextureType;
using Tegra::Texture::TICEntry;
using VideoCore::Surface::PixelFormat;
@@ -107,12 +110,13 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept {
}
}
-ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) noexcept {
+ImageInfo::ImageInfo(const Maxwell3D::Regs& regs, size_t index) noexcept {
const auto& rt = regs.rt[index];
format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(rt.format);
rescaleable = false;
if (rt.tile_mode.is_pitch_linear) {
- ASSERT(rt.tile_mode.is_3d == 0);
+ ASSERT(rt.tile_mode.dim_control ==
+ Maxwell3D::Regs::TileMode::DimensionControl::DepthDefinesArray);
type = ImageType::Linear;
pitch = rt.width;
size = Extent3D{
@@ -124,15 +128,16 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index)
}
size.width = rt.width;
size.height = rt.height;
- layer_stride = rt.layer_stride * 4;
+ layer_stride = rt.array_pitch * 4;
maybe_unaligned_layer_stride = layer_stride;
- num_samples = NumSamples(regs.multisample_mode);
+ num_samples = NumSamples(regs.anti_alias_samples_mode);
block = Extent3D{
.width = rt.tile_mode.block_width,
.height = rt.tile_mode.block_height,
.depth = rt.tile_mode.block_depth,
};
- if (rt.tile_mode.is_3d) {
+ if (rt.tile_mode.dim_control ==
+ Maxwell3D::Regs::TileMode::DimensionControl::DepthDefinesDepth) {
type = ImageType::e3D;
size.depth = rt.depth;
} else {
@@ -146,31 +151,37 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index)
ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept {
format = VideoCore::Surface::PixelFormatFromDepthFormat(regs.zeta.format);
- size.width = regs.zeta_width;
- size.height = regs.zeta_height;
+ size.width = regs.zeta_size.width;
+ size.height = regs.zeta_size.height;
rescaleable = false;
resources.levels = 1;
- layer_stride = regs.zeta.layer_stride * 4;
+ layer_stride = regs.zeta.array_pitch * 4;
maybe_unaligned_layer_stride = layer_stride;
- num_samples = NumSamples(regs.multisample_mode);
+ num_samples = NumSamples(regs.anti_alias_samples_mode);
block = Extent3D{
.width = regs.zeta.tile_mode.block_width,
.height = regs.zeta.tile_mode.block_height,
.depth = regs.zeta.tile_mode.block_depth,
};
if (regs.zeta.tile_mode.is_pitch_linear) {
- ASSERT(regs.zeta.tile_mode.is_3d == 0);
+ ASSERT(regs.zeta.tile_mode.dim_control ==
+ Maxwell3D::Regs::TileMode::DimensionControl::DepthDefinesArray);
type = ImageType::Linear;
pitch = size.width * BytesPerBlock(format);
- } else if (regs.zeta.tile_mode.is_3d) {
+ } else if (regs.zeta.tile_mode.dim_control ==
+ Maxwell3D::Regs::TileMode::DimensionControl::DepthDefinesDepth) {
ASSERT(regs.zeta.tile_mode.is_pitch_linear == 0);
+ ASSERT(regs.zeta_size.dim_control ==
+ Maxwell3D::Regs::ZetaSize::DimensionControl::ArraySizeOne);
type = ImageType::e3D;
- size.depth = regs.zeta_depth;
+ size.depth = regs.zeta_size.depth;
} else {
+ ASSERT(regs.zeta_size.dim_control ==
+ Maxwell3D::Regs::ZetaSize::DimensionControl::DepthDefinesArray);
rescaleable = block.depth == 0;
downscaleable = size.height > 512;
type = ImageType::e2D;
- resources.layers = regs.zeta_depth;
+ resources.layers = regs.zeta_size.depth;
}
}
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index eaf4a1c95..413baf730 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -189,15 +189,16 @@ typename P::Sampler* TextureCache<P>::GetComputeSampler(u32 index) {
template <class P>
void TextureCache<P>::SynchronizeGraphicsDescriptors() {
- using SamplerIndex = Tegra::Engines::Maxwell3D::Regs::SamplerIndex;
- const bool linked_tsc = maxwell3d->regs.sampler_index == SamplerIndex::ViaHeaderIndex;
- const u32 tic_limit = maxwell3d->regs.tic.limit;
- const u32 tsc_limit = linked_tsc ? tic_limit : maxwell3d->regs.tsc.limit;
- if (channel_state->graphics_sampler_table.Synchornize(maxwell3d->regs.tsc.Address(),
+ using SamplerBinding = Tegra::Engines::Maxwell3D::Regs::SamplerBinding;
+ const bool linked_tsc = maxwell3d->regs.sampler_binding == SamplerBinding::ViaHeaderBinding;
+ const u32 tic_limit = maxwell3d->regs.tex_header.limit;
+ const u32 tsc_limit = linked_tsc ? tic_limit : maxwell3d->regs.tex_sampler.limit;
+ if (channel_state->graphics_sampler_table.Synchornize(maxwell3d->regs.tex_sampler.Address(),
tsc_limit)) {
channel_state->graphics_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
}
- if (channel_state->graphics_image_table.Synchornize(maxwell3d->regs.tic.Address(), tic_limit)) {
+ if (channel_state->graphics_image_table.Synchornize(maxwell3d->regs.tex_header.Address(),
+ tic_limit)) {
channel_state->graphics_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
}
}
@@ -352,8 +353,8 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
down_shift = Settings::values.resolution_info.down_shift;
}
render_targets.size = Extent2D{
- (maxwell3d->regs.render_area.width * up_scale) >> down_shift,
- (maxwell3d->regs.render_area.height * up_scale) >> down_shift,
+ (maxwell3d->regs.surface_clip.width * up_scale) >> down_shift,
+ (maxwell3d->regs.surface_clip.height * up_scale) >> down_shift,
};
render_targets.is_rescaled = is_rescaling;
@@ -1980,7 +1981,7 @@ bool TextureCache<P>::IsFullClear(ImageViewId id) {
// Images with multiple resources can't be cleared in a single call
return false;
}
- if (regs.clear_flags.scissor == 0) {
+ if (regs.clear_control.use_scissor == 0) {
// If scissor testing is disabled, the clear is always full
return true;
}
diff --git a/src/video_core/transform_feedback.cpp b/src/video_core/transform_feedback.cpp
index 7e605981c..45071185a 100644
--- a/src/video_core/transform_feedback.cpp
+++ b/src/video_core/transform_feedback.cpp
@@ -15,51 +15,51 @@ namespace VideoCommon {
std::vector<Shader::TransformFeedbackVarying> MakeTransformFeedbackVaryings(
const TransformFeedbackState& state) {
static constexpr std::array VECTORS{
- 28, // gl_Position
- 32, // Generic 0
- 36, // Generic 1
- 40, // Generic 2
- 44, // Generic 3
- 48, // Generic 4
- 52, // Generic 5
- 56, // Generic 6
- 60, // Generic 7
- 64, // Generic 8
- 68, // Generic 9
- 72, // Generic 10
- 76, // Generic 11
- 80, // Generic 12
- 84, // Generic 13
- 88, // Generic 14
- 92, // Generic 15
- 96, // Generic 16
- 100, // Generic 17
- 104, // Generic 18
- 108, // Generic 19
- 112, // Generic 20
- 116, // Generic 21
- 120, // Generic 22
- 124, // Generic 23
- 128, // Generic 24
- 132, // Generic 25
- 136, // Generic 26
- 140, // Generic 27
- 144, // Generic 28
- 148, // Generic 29
- 152, // Generic 30
- 156, // Generic 31
- 160, // gl_FrontColor
- 164, // gl_FrontSecondaryColor
- 160, // gl_BackColor
- 164, // gl_BackSecondaryColor
- 192, // gl_TexCoord[0]
- 196, // gl_TexCoord[1]
- 200, // gl_TexCoord[2]
- 204, // gl_TexCoord[3]
- 208, // gl_TexCoord[4]
- 212, // gl_TexCoord[5]
- 216, // gl_TexCoord[6]
- 220, // gl_TexCoord[7]
+ 28U, // gl_Position
+ 32U, // Generic 0
+ 36U, // Generic 1
+ 40U, // Generic 2
+ 44U, // Generic 3
+ 48U, // Generic 4
+ 52U, // Generic 5
+ 56U, // Generic 6
+ 60U, // Generic 7
+ 64U, // Generic 8
+ 68U, // Generic 9
+ 72U, // Generic 10
+ 76U, // Generic 11
+ 80U, // Generic 12
+ 84U, // Generic 13
+ 88U, // Generic 14
+ 92U, // Generic 15
+ 96U, // Generic 16
+ 100U, // Generic 17
+ 104U, // Generic 18
+ 108U, // Generic 19
+ 112U, // Generic 20
+ 116U, // Generic 21
+ 120U, // Generic 22
+ 124U, // Generic 23
+ 128U, // Generic 24
+ 132U, // Generic 25
+ 136U, // Generic 26
+ 140U, // Generic 27
+ 144U, // Generic 28
+ 148U, // Generic 29
+ 152U, // Generic 30
+ 156U, // Generic 31
+ 160U, // gl_FrontColor
+ 164U, // gl_FrontSecondaryColor
+ 160U, // gl_BackColor
+ 164U, // gl_BackSecondaryColor
+ 192U, // gl_TexCoord[0]
+ 196U, // gl_TexCoord[1]
+ 200U, // gl_TexCoord[2]
+ 204U, // gl_TexCoord[3]
+ 208U, // gl_TexCoord[4]
+ 212U, // gl_TexCoord[5]
+ 216U, // gl_TexCoord[6]
+ 220U, // gl_TexCoord[7]
};
std::vector<Shader::TransformFeedbackVarying> xfb(256);
for (size_t buffer = 0; buffer < state.layouts.size(); ++buffer) {
@@ -68,8 +68,20 @@ std::vector<Shader::TransformFeedbackVarying> MakeTransformFeedbackVaryings(
const u32 varying_count = layout.varying_count;
u32 highest = 0;
for (u32 offset = 0; offset < varying_count; ++offset) {
- const u32 base_offset = offset;
- const u8 location = locations[offset];
+ const auto get_attribute = [&locations](u32 index) -> u32 {
+ switch (index % 4) {
+ case 0:
+ return locations[index / 4].attribute0.Value();
+ case 1:
+ return locations[index / 4].attribute1.Value();
+ case 2:
+ return locations[index / 4].attribute2.Value();
+ case 3:
+ return locations[index / 4].attribute3.Value();
+ }
+ UNREACHABLE();
+ return 0;
+ };
UNIMPLEMENTED_IF_MSG(layout.stream != 0, "Stream is not zero: {}", layout.stream);
Shader::TransformFeedbackVarying varying{
@@ -78,16 +90,18 @@ std::vector<Shader::TransformFeedbackVarying> MakeTransformFeedbackVaryings(
.offset = offset * 4,
.components = 1,
};
- if (std::ranges::find(VECTORS, Common::AlignDown(location, 4)) != VECTORS.end()) {
- UNIMPLEMENTED_IF_MSG(location % 4 != 0, "Unaligned TFB");
+ const u32 base_offset = offset;
+ const auto attribute{get_attribute(offset)};
+ if (std::ranges::find(VECTORS, Common::AlignDown(attribute, 4)) != VECTORS.end()) {
+ UNIMPLEMENTED_IF_MSG(attribute % 4 != 0, "Unaligned TFB {}", attribute);
- const u8 base_index = location / 4;
- while (offset + 1 < varying_count && base_index == locations[offset + 1] / 4) {
+ const auto base_index = attribute / 4;
+ while (offset + 1 < varying_count && base_index == get_attribute(offset + 1) / 4) {
++offset;
++varying.components;
}
}
- xfb[location] = varying;
+ xfb[attribute] = varying;
highest = std::max(highest, (base_offset + varying.components) * 4);
}
UNIMPLEMENTED_IF(highest != layout.stride);
diff --git a/src/video_core/transform_feedback.h b/src/video_core/transform_feedback.h
index a519adb59..d13eb16c3 100644
--- a/src/video_core/transform_feedback.h
+++ b/src/video_core/transform_feedback.h
@@ -19,7 +19,8 @@ struct TransformFeedbackState {
u32 stride;
};
std::array<Layout, Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers> layouts;
- std::array<std::array<u8, 128>, Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers>
+ std::array<std::array<Tegra::Engines::Maxwell3D::Regs::StreamOutLayout, 32>,
+ Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers>
varyings;
};
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index 87e5d0f48..bd69d04a6 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -57,9 +57,10 @@ ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* paren
UpdateBackgroundColorButton(new_bg_color);
});
- ui->api->setEnabled(!UISettings::values.has_broken_vulkan);
- ui->api_widget->setEnabled(!UISettings::values.has_broken_vulkan ||
- Settings::IsConfiguringGlobal());
+ ui->api->setEnabled(!UISettings::values.has_broken_vulkan && ui->api->isEnabled());
+ ui->api_widget->setEnabled(
+ (!UISettings::values.has_broken_vulkan || Settings::IsConfiguringGlobal()) &&
+ ui->api_widget->isEnabled());
ui->bg_label->setVisible(Settings::IsConfiguringGlobal());
ui->bg_combobox->setVisible(!Settings::IsConfiguringGlobal());
}
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui
index 1e4f74704..fdbb33372 100644
--- a/src/yuzu/configuration/configure_graphics.ui
+++ b/src/yuzu/configuration/configure_graphics.ui
@@ -301,6 +301,11 @@
</item>
<item>
<property name="text">
+ <string>Force 16:10</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
<string>Stretch to Window</string>
</property>
</item>
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 4146ebc2c..f45a25410 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -262,6 +262,18 @@ static QString PrettyProductName() {
return QSysInfo::prettyProductName();
}
+#ifdef _WIN32
+static void OverrideWindowsFont() {
+ // Qt5 chooses these fonts on Windows and they have fairly ugly alphanumeric/cyrllic characters
+ // Asking to use "MS Shell Dlg 2" gives better other chars while leaving the Chinese Characters.
+ const QString startup_font = QApplication::font().family();
+ const QStringList ugly_fonts = {QStringLiteral("SimSun"), QStringLiteral("PMingLiU")};
+ if (ugly_fonts.contains(startup_font)) {
+ QApplication::setFont(QFont(QStringLiteral("MS Shell Dlg 2"), 9, QFont::Normal));
+ }
+}
+#endif
+
bool GMainWindow::CheckDarkMode() {
#ifdef __linux__
const QPalette test_palette(qApp->palette());
@@ -4137,6 +4149,10 @@ int main(int argc, char* argv[]) {
QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity);
QApplication app(argc, argv);
+#ifdef _WIN32
+ OverrideWindowsFont();
+#endif
+
// Workaround for QTBUG-85409, for Suzhou numerals the number 1 is actually \u3021
// so we can see if we get \u3008 instead
// TL;DR all other number formats are consecutive in unicode code points