2020-02-21 00:35:53 +01:00
|
|
|
// Copyright 2020 yuzu Emulator Project
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
2020-02-21 05:19:07 +01:00
|
|
|
#include <algorithm>
|
2020-12-30 06:25:23 +01:00
|
|
|
#include <array>
|
2020-02-21 05:19:07 +01:00
|
|
|
#include <cstddef>
|
2020-02-21 00:35:53 +01:00
|
|
|
|
|
|
|
#include "common/common_types.h"
|
|
|
|
#include "core/core.h"
|
2020-02-21 05:56:00 +01:00
|
|
|
#include "video_core/dirty_flags.h"
|
2020-02-21 00:35:53 +01:00
|
|
|
#include "video_core/engines/maxwell_3d.h"
|
|
|
|
#include "video_core/gpu.h"
|
|
|
|
#include "video_core/renderer_vulkan/vk_state_tracker.h"
|
|
|
|
|
|
|
|
#define OFF(field_name) MAXWELL3D_REG_INDEX(field_name)
|
2020-11-15 01:01:33 +01:00
|
|
|
#define NUM(field_name) (sizeof(Maxwell3D::Regs::field_name) / (sizeof(u32)))
|
2020-02-21 00:35:53 +01:00
|
|
|
|
|
|
|
namespace Vulkan {
|
|
|
|
namespace {
|
|
|
|
using namespace Dirty;
|
|
|
|
using namespace VideoCommon::Dirty;
|
|
|
|
using Tegra::Engines::Maxwell3D;
|
|
|
|
using Regs = Maxwell3D::Regs;
|
2020-02-21 05:19:07 +01:00
|
|
|
using Tables = Maxwell3D::DirtyState::Tables;
|
|
|
|
using Table = Maxwell3D::DirtyState::Table;
|
|
|
|
using Flags = Maxwell3D::DirtyState::Flags;
|
2020-02-21 00:35:53 +01:00
|
|
|
|
|
|
|
Flags MakeInvalidationFlags() {
|
2021-01-17 00:48:58 +01:00
|
|
|
static constexpr int INVALIDATION_FLAGS[]{
|
2021-06-25 10:21:51 +02:00
|
|
|
Viewports, Scissors, DepthBias, BlendConstants, DepthBounds,
|
|
|
|
StencilProperties, LineWidth, CullMode, DepthBoundsEnable, DepthTestEnable,
|
|
|
|
DepthWriteEnable, DepthCompareOp, FrontFace, StencilOp, StencilTestEnable,
|
|
|
|
VertexBuffers, VertexInput,
|
2020-12-30 06:25:23 +01:00
|
|
|
};
|
2020-02-21 00:35:53 +01:00
|
|
|
Flags flags{};
|
2020-12-30 06:25:23 +01:00
|
|
|
for (const int flag : INVALIDATION_FLAGS) {
|
|
|
|
flags[flag] = true;
|
|
|
|
}
|
2021-01-17 00:48:58 +01:00
|
|
|
for (int index = VertexBuffer0; index <= VertexBuffer31; ++index) {
|
|
|
|
flags[index] = true;
|
|
|
|
}
|
2021-06-12 10:07:52 +02:00
|
|
|
for (int index = VertexAttribute0; index <= VertexAttribute31; ++index) {
|
|
|
|
flags[index] = true;
|
|
|
|
}
|
|
|
|
for (int index = VertexBinding0; index <= VertexBinding31; ++index) {
|
|
|
|
flags[index] = true;
|
|
|
|
}
|
2020-02-21 00:35:53 +01:00
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2021-10-19 10:03:45 +02:00
|
|
|
tables[1][OFF(screen_y_control)] = Viewports;
|
2020-02-21 00:35:53 +01:00
|
|
|
}
|
|
|
|
|
2020-02-21 02:19:57 +01:00
|
|
|
void SetupDirtyScissors(Tables& tables) {
|
|
|
|
FillBlock(tables[0], OFF(scissor_test), NUM(scissor_test), Scissors);
|
|
|
|
}
|
|
|
|
|
2020-02-21 04:28:45 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-02-21 04:37:29 +01:00
|
|
|
void SetupDirtyBlendConstants(Tables& tables) {
|
|
|
|
FillBlock(tables[0], OFF(blend_color), NUM(blend_color), BlendConstants);
|
|
|
|
}
|
|
|
|
|
2020-02-21 04:54:39 +01:00
|
|
|
void SetupDirtyDepthBounds(Tables& tables) {
|
|
|
|
FillBlock(tables[0], OFF(depth_bounds), NUM(depth_bounds), DepthBounds);
|
|
|
|
}
|
|
|
|
|
2020-02-21 05:09:02 +01:00
|
|
|
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_mask)] = StencilProperties;
|
|
|
|
table[OFF(stencil_front_func_mask)] = StencilProperties;
|
|
|
|
table[OFF(stencil_back_func_ref)] = StencilProperties;
|
|
|
|
table[OFF(stencil_back_mask)] = StencilProperties;
|
|
|
|
table[OFF(stencil_back_func_mask)] = StencilProperties;
|
|
|
|
}
|
|
|
|
|
2021-06-25 10:21:51 +02:00
|
|
|
void SetupDirtyLineWidth(Tables& tables) {
|
|
|
|
tables[0][OFF(line_width_smooth)] = LineWidth;
|
|
|
|
tables[0][OFF(line_width_aliased)] = LineWidth;
|
|
|
|
}
|
|
|
|
|
2020-06-22 08:03:27 +02:00
|
|
|
void SetupDirtyCullMode(Tables& tables) {
|
|
|
|
auto& table = tables[0];
|
|
|
|
table[OFF(cull_face)] = CullMode;
|
|
|
|
table[OFF(cull_test_enabled)] = CullMode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetupDirtyDepthBoundsEnable(Tables& tables) {
|
|
|
|
tables[0][OFF(depth_bounds_enable)] = DepthBoundsEnable;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetupDirtyDepthTestEnable(Tables& tables) {
|
|
|
|
tables[0][OFF(depth_test_enable)] = DepthTestEnable;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetupDirtyDepthWriteEnable(Tables& tables) {
|
|
|
|
tables[0][OFF(depth_write_enabled)] = DepthWriteEnable;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetupDirtyDepthCompareOp(Tables& tables) {
|
|
|
|
tables[0][OFF(depth_test_func)] = DepthCompareOp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetupDirtyFrontFace(Tables& tables) {
|
|
|
|
auto& table = tables[0];
|
|
|
|
table[OFF(front_face)] = FrontFace;
|
|
|
|
table[OFF(screen_y_control)] = 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 0 is used by StencilProperties
|
|
|
|
tables[1][OFF(stencil_two_side_enable)] = StencilOp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetupDirtyStencilTestEnable(Tables& tables) {
|
|
|
|
tables[0][OFF(stencil_enable)] = StencilTestEnable;
|
|
|
|
}
|
|
|
|
|
2021-01-19 06:04:27 +01:00
|
|
|
void SetupDirtyBlending(Tables& tables) {
|
|
|
|
tables[0][OFF(color_mask_common)] = Blending;
|
|
|
|
tables[0][OFF(independent_blend_enable)] = 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);
|
|
|
|
}
|
|
|
|
|
2021-06-12 10:07:52 +02:00
|
|
|
void SetupDirtyViewportSwizzles(Tables& tables) {
|
|
|
|
static constexpr size_t swizzle_offset = 6;
|
|
|
|
for (size_t index = 0; index < Regs::NumViewports; ++index) {
|
|
|
|
tables[0][OFF(viewport_transform) + index * NUM(viewport_transform[0]) + swizzle_offset] =
|
|
|
|
ViewportSwizzles;
|
2021-01-19 06:04:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetupDirtyVertexAttributes(Tables& tables) {
|
2021-06-12 10:07:52 +02:00
|
|
|
for (size_t i = 0; i < Regs::NumVertexAttributes; ++i) {
|
|
|
|
const size_t offset = OFF(vertex_attrib_format) + i * NUM(vertex_attrib_format[0]);
|
|
|
|
FillBlock(tables[0], offset, NUM(vertex_attrib_format[0]), VertexAttribute0 + i);
|
|
|
|
}
|
|
|
|
FillBlock(tables[1], OFF(vertex_attrib_format), Regs::NumVertexAttributes, VertexInput);
|
2021-01-19 06:04:27 +01:00
|
|
|
}
|
|
|
|
|
2021-06-12 10:07:52 +02:00
|
|
|
void SetupDirtyVertexBindings(Tables& tables) {
|
|
|
|
// Do NOT include stride here, it's implicit in VertexBuffer
|
|
|
|
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;
|
2021-01-19 06:04:27 +01:00
|
|
|
}
|
|
|
|
}
|
2020-02-21 00:35:53 +01:00
|
|
|
} // Anonymous namespace
|
|
|
|
|
2020-06-12 02:24:45 +02:00
|
|
|
StateTracker::StateTracker(Tegra::GPU& gpu)
|
|
|
|
: flags{gpu.Maxwell3D().dirty.flags}, invalidation_flags{MakeInvalidationFlags()} {
|
2021-06-12 10:07:52 +02:00
|
|
|
auto& tables{gpu.Maxwell3D().dirty.tables};
|
2021-01-17 00:48:58 +01:00
|
|
|
SetupDirtyFlags(tables);
|
2020-02-21 00:35:53 +01:00
|
|
|
SetupDirtyViewports(tables);
|
2020-02-21 02:19:57 +01:00
|
|
|
SetupDirtyScissors(tables);
|
2020-02-21 04:28:45 +01:00
|
|
|
SetupDirtyDepthBias(tables);
|
2020-02-21 04:37:29 +01:00
|
|
|
SetupDirtyBlendConstants(tables);
|
2020-02-21 04:54:39 +01:00
|
|
|
SetupDirtyDepthBounds(tables);
|
2020-02-21 05:09:02 +01:00
|
|
|
SetupDirtyStencilProperties(tables);
|
2021-06-25 10:21:51 +02:00
|
|
|
SetupDirtyLineWidth(tables);
|
2020-06-22 08:03:27 +02:00
|
|
|
SetupDirtyCullMode(tables);
|
|
|
|
SetupDirtyDepthBoundsEnable(tables);
|
|
|
|
SetupDirtyDepthTestEnable(tables);
|
|
|
|
SetupDirtyDepthWriteEnable(tables);
|
|
|
|
SetupDirtyDepthCompareOp(tables);
|
|
|
|
SetupDirtyFrontFace(tables);
|
|
|
|
SetupDirtyStencilOp(tables);
|
2020-07-13 01:43:42 +02:00
|
|
|
SetupDirtyStencilTestEnable(tables);
|
2021-01-19 06:04:27 +01:00
|
|
|
SetupDirtyBlending(tables);
|
|
|
|
SetupDirtyViewportSwizzles(tables);
|
2021-06-12 10:07:52 +02:00
|
|
|
SetupDirtyVertexAttributes(tables);
|
|
|
|
SetupDirtyVertexBindings(tables);
|
2020-02-21 00:35:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Vulkan
|