Compare commits

..

11 Commits

Author SHA1 Message Date
Liam
5b7c0f13d3 fsp_srv: stub GetCacheStorageSize 2022-10-08 12:24:00 -04:00
Mai
155213484b Merge pull request #9016 from liamwhite/drunken-schedule
vk_scheduler: wait for command processing to complete
2022-10-07 20:27:16 -04:00
Mai
b7ad83383f Merge pull request #8932 from abouvier/cmake-pkgconfig
cmake: Fix FindPkgConfig
2022-10-07 20:25:51 -04:00
Mai
6f101e0f02 Merge pull request #9030 from Morph1984/api-disable
configure_graphics: Fix graphics API selection when a game is running
2022-10-07 20:25:23 -04:00
liamwhite
972b93bf00 Merge pull request #8807 from Docteh/default_fonts
Qt: work around Qt5's font choice for Chinese (in Windows)
2022-10-07 17:39:39 -04:00
Morph
1e35ade1ec configure_graphics: Fix graphics API selection when a game is running
The graphics API setting should not be changed when a game is running.
2022-10-07 15:11:26 -04:00
Narr the Reg
b8777b6653 Merge pull request #9028 from liamwhite/wtype-limits
nfp_types: silence -Wtype-limits
2022-10-07 09:03:35 -05:00
Liam
9574429c5f nfp_types: silence -Wtype-limits 2022-10-07 06:52:28 -04:00
Liam
7969d4d5de vk_scheduler: wait for command processing to complete 2022-10-03 20:03:25 -04:00
Kyle Kienapfel
1dba5fab62 Qt: work around Qt5's font choice for Chinese
On Windows there are currently two fonts used.

The first, does the Menu, QTreeView and Tooltips
Second is Everything else which is a default font.

From inspecting QApplication::font() at runtime
Windows 10 English: QFont(MS Shell Dlg 2,8.25,-1,5,50,0,0,0,0,0)
Windows 11 Japanese:        MS UI Gothic,9   ,-1,5,50,0,0,0,0,0
Windows 11 Traditional Chinese: PMingLiU,9   ,-1,5,50,0,0,0,0,0
Windows 11 Simplified Chinese:    SimSun,9   ,-1,5,50,0,0,0,0,0
Windows 11 Korean:                 Gulim,9   ,-1,5,50,0,0,0,0,0

I initially investigated dynamically changing the font when
the UI language is English, but this was getting quite messy

Qt6 makes changes to default font in some situations, so this
PR is being narrowed in scope to only effect Chinese font choices.
This change only effects rendering of Latin/Cyrillic characters.
2022-10-01 15:27:23 -07:00
Alexandre Bouvier
09a87966e0 cmake: Fix FindPkgConfig 2022-09-20 22:21:52 +02:00
38 changed files with 2202 additions and 4101 deletions

View File

@@ -252,7 +252,7 @@ if(ENABLE_QT)
endif()
# Check for headers
Include(FindPkgConfig REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(QT_DEP_GLU QUIET glu>=9.0.0)
if (NOT QT_DEP_GLU_FOUND)
message(FATAL_ERROR "Qt bundled pacakge dependency `glu` not found. \
@@ -386,7 +386,7 @@ endif()
# Ensure libusb is properly configured (based on dolphin libusb include)
if(NOT APPLE AND NOT YUZU_USE_BUNDLED_LIBUSB)
include(FindPkgConfig)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND AND NOT CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD")
pkg_check_modules(LIBUSB QUIET libusb-1.0>=1.0.24)
else()
@@ -410,7 +410,7 @@ set(FFmpeg_COMPONENTS
swscale)
if (UNIX AND NOT APPLE)
Include(FindPkgConfig REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBVA libva)
endif()
if (NOT YUZU_USE_BUNDLED_FFMPEG)

View File

@@ -43,7 +43,7 @@ if (NOT WIN32)
CACHE PATH "Paths to FFmpeg libraries" FORCE)
endforeach()
Include(FindPkgConfig REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBVA libva)
pkg_check_modules(CUDA cuda)
pkg_check_modules(FFNVCODEC ffnvcodec)

View File

@@ -108,7 +108,7 @@ if (MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux") OR APPLE)
target_include_directories(usb INTERFACE "${LIBUSB_INCLUDE_DIRS}")
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
Include(FindPkgConfig)
find_package(PkgConfig)
pkg_check_modules(LIBUDEV REQUIRED libudev)
if (LIBUDEV_FOUND)

View File

@@ -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_)

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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_buffer.first *
maxwell3d->regs.index_buffer.FormatSizeInBytes();
const u32 new_offset = offset + maxwell3d->regs.index_array.first *
maxwell3d->regs.index_array.FormatSizeInBytes();
runtime.BindIndexBuffer(buffer, new_offset, size);
} else {
runtime.BindIndexBuffer(maxwell3d->regs.draw.topology, maxwell3d->regs.index_buffer.format,
maxwell3d->regs.index_buffer.first,
maxwell3d->regs.index_buffer.count, buffer, offset, size);
runtime.BindIndexBuffer(maxwell3d->regs.draw.topology, maxwell3d->regs.index_array.format,
maxwell3d->regs.index_array.first,
maxwell3d->regs.index_array.count, buffer, offset, size);
}
}
@@ -1017,7 +1017,7 @@ void BufferCache<P>::BindHostVertexBuffers() {
}
flags[Dirty::VertexBuffer0 + index] = false;
const u32 stride = maxwell3d->regs.vertex_streams[index].stride;
const u32 stride = maxwell3d->regs.vertex_array[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.transform_feedback_enabled == 0) {
if (maxwell3d->regs.tfb_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_buffer;
const auto& index_array = maxwell3d->regs.index_array;
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_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 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 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.transform_feedback_enabled == 0) {
if (maxwell3d->regs.tfb_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.transform_feedback.buffers[index];
const GPUVAddr gpu_addr = binding.Address() + binding.start_offset;
const u32 size = binding.size;
const auto& binding = maxwell3d->regs.tfb_bindings[index];
const GPUVAddr gpu_addr = binding.Address() + binding.buffer_offset;
const u32 size = binding.buffer_size;
const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
if (binding.enable == 0 || size == 0 || !cpu_addr) {
if (binding.buffer_enable == 0 || size == 0 || !cpu_addr) {
transform_feedback_buffers[index] = NULL_BINDING;
return;
}

View File

@@ -17,23 +17,21 @@ 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_streams) + i * NUM(vertex_streams[0]);
const std::size_t limit_offset =
OFF(vertex_stream_limits) + i * NUM(vertex_stream_limits[0]);
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]);
FillBlock(tables, array_offset, num_array, VertexBuffer0 + i, VertexBuffers);
FillBlock(tables, limit_offset, NUM(vertex_stream_limits), VertexBuffer0 + i,
VertexBuffers);
FillBlock(tables, limit_offset, NUM(vertex_array_limit), VertexBuffer0 + i, VertexBuffers);
}
}
void SetupIndexBuffer(Maxwell3D::DirtyState::Tables& tables) {
FillBlock(tables[0], OFF(index_buffer), NUM(index_buffer), IndexBuffer);
FillBlock(tables[0], OFF(index_array), NUM(index_array), IndexBuffer);
}
void SetupDirtyDescriptors(Maxwell3D::DirtyState::Tables& tables) {
FillBlock(tables[0], OFF(tex_header), NUM(tex_header), Descriptors);
FillBlock(tables[0], OFF(tex_sampler), NUM(tex_sampler), Descriptors);
FillBlock(tables[0], OFF(tic), NUM(tic), Descriptors);
FillBlock(tables[0], OFF(tsc), NUM(tsc), Descriptors);
}
void SetupDirtyRenderTargets(Maxwell3D::DirtyState::Tables& tables) {
@@ -44,7 +42,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(surface_clip), NUM(surface_clip), RenderTargets);
FillBlock(tables[0], OFF(render_area), NUM(render_area), RenderTargets);
tables[0][OFF(rt_control)] = RenderTargets;
tables[1][OFF(rt_control)] = RenderTargetControl;
@@ -54,15 +52,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_size.width)] = flag;
table[OFF(zeta_size.height)] = flag;
table[OFF(zeta_width)] = flag;
table[OFF(zeta_height)] = flag;
FillBlock(table, OFF(zeta), NUM(zeta), flag);
}
}
void SetupDirtyShaders(Maxwell3D::DirtyState::Tables& tables) {
FillBlock(tables[0], OFF(pipelines), NUM(pipelines) * Maxwell3D::Regs::MaxShaderProgram,
Shaders);
FillBlock(tables[0], OFF(shader_config[0]),
NUM(shader_config[0]) * Maxwell3D::Regs::MaxShaderProgram, Shaders);
}
} // Anonymous namespace

View File

@@ -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.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.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::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.func_mask = 0xFFFFFFFF;
regs.stencil_front_func.mask = 0xFFFFFFFF;
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.stencil_front_func_mask = 0xFFFFFFFF;
regs.stencil_front_mask = 0xFFFFFFFF;
regs.stencil_two_side_enable = 1;
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.func_mask = 0xFFFFFFFF;
regs.stencil_back_func.mask = 0xFFFFFFFF;
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_func_mask = 0xFFFFFFFF;
regs.stencil_back_mask = 0xFFFFFFFF;
regs.depth_test_func = Regs::ComparisonOp::Always_GL;
regs.gl_front_face = Regs::FrontFace::CounterClockWise;
regs.gl_cull_face = Regs::CullFace::Back;
regs.depth_test_func = Regs::ComparisonOp::Always;
regs.front_face = Regs::FrontFace::CounterClockWise;
regs.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.color_target_mrt_enable = 1;
regs.rt_separate_frag_data = 1;
regs.framebuffer_srgb = 1;
regs.line_width_aliased = 1.0f;
regs.line_width_smooth = 1.0f;
regs.gl_front_face = Maxwell3D::Regs::FrontFace::ClockWise;
regs.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.end)] = true;
mme_inline[MAXWELL3D_REG_INDEX(draw.begin)] = true;
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(vertex_buffer.count)] = true;
mme_inline[MAXWELL3D_REG_INDEX(index_buffer.count)] = true;
mme_inline[MAXWELL3D_REG_INDEX(index_array.count)] = true;
}
void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) {
@@ -173,56 +173,51 @@ 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(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):
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):
return ProcessMacroBind(argument);
case MAXWELL3D_REG_INDEX(falcon[4]):
case MAXWELL3D_REG_INDEX(firmware[4]):
return ProcessFirmwareCall4();
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:
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:
return ProcessCBData(argument);
case MAXWELL3D_REG_INDEX(bind_groups[0].raw_config):
case MAXWELL3D_REG_INDEX(cb_bind[0]):
return ProcessCBBind(0);
case MAXWELL3D_REG_INDEX(bind_groups[1].raw_config):
case MAXWELL3D_REG_INDEX(cb_bind[1]):
return ProcessCBBind(1);
case MAXWELL3D_REG_INDEX(bind_groups[2].raw_config):
case MAXWELL3D_REG_INDEX(cb_bind[2]):
return ProcessCBBind(2);
case MAXWELL3D_REG_INDEX(bind_groups[3].raw_config):
case MAXWELL3D_REG_INDEX(cb_bind[3]):
return ProcessCBBind(3);
case MAXWELL3D_REG_INDEX(bind_groups[4].raw_config):
case MAXWELL3D_REG_INDEX(cb_bind[4]):
return ProcessCBBind(4);
case MAXWELL3D_REG_INDEX(draw.end):
case MAXWELL3D_REG_INDEX(draw.vertex_end_gl):
return DrawArrays();
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;
case MAXWELL3D_REG_INDEX(small_index):
regs.index_array.count = regs.small_index.count;
regs.index_array.first = regs.small_index.first;
dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
return DrawArrays();
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;
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;
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.
@@ -230,24 +225,28 @@ 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_surface):
case MAXWELL3D_REG_INDEX(clear_buffers):
return ProcessClearBuffers();
case MAXWELL3D_REG_INDEX(report_semaphore.query):
case MAXWELL3D_REG_INDEX(query.query_get):
return ProcessQueryGet();
case MAXWELL3D_REG_INDEX(render_enable.mode):
case MAXWELL3D_REG_INDEX(condition.mode):
return ProcessQueryCondition();
case MAXWELL3D_REG_INDEX(clear_report_value):
case MAXWELL3D_REG_INDEX(counter_reset):
return ProcessCounterReset();
case MAXWELL3D_REG_INDEX(sync_info):
return ProcessSyncPoint();
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):
case MAXWELL3D_REG_INDEX(exec_upload):
return upload_state.ProcessExec(regs.exec_upload.linear != 0);
case MAXWELL3D_REG_INDEX(data_upload):
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();
}
}
@@ -297,25 +296,25 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount,
return;
}
switch (method) {
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:
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:
ProcessCBMultiData(base_start, amount);
break;
case MAXWELL3D_REG_INDEX(inline_data):
case MAXWELL3D_REG_INDEX(data_upload):
upload_state.ProcessData(base_start, static_cast<size_t>(amount));
return;
default:
@@ -354,15 +353,14 @@ 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_buffer.count)) {
method == MAXWELL3D_REG_INDEX(index_array.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.begin)) {
} else if (method == MAXWELL3D_REG_INDEX(draw.vertex_begin_gl)) {
mme_draw.instance_mode =
(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) ||
(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged);
(regs.draw.instance_next != 0) || (regs.draw.instance_cont != 0);
mme_draw.gl_begin_consume = true;
} else {
mme_draw.gl_end_count++;
@@ -407,12 +405,11 @@ 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_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?");
ASSERT_MSG(!(regs.index_array.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_id == Maxwell3D::Regs::Draw::InstanceId::First ||
regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
ASSERT_MSG(!regs.draw.instance_next || !regs.draw.instance_cont,
"Illegal combination of instancing parameters");
ProcessTopologyOverride();
@@ -427,7 +424,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_buffer.count = 0;
regs.index_array.count = 0;
} else {
regs.vertex_buffer.count = 0;
}
@@ -440,11 +437,11 @@ void Maxwell3D::FlushMMEInlineDraw() {
}
void Maxwell3D::ProcessMacroUpload(u32 data) {
macro_engine->AddCode(regs.load_mme.instruction_ptr++, data);
macro_engine->AddCode(regs.macros.upload_address++, data);
}
void Maxwell3D::ProcessMacroBind(u32 data) {
macro_positions[regs.load_mme.start_address_ptr++] = data;
macro_positions[regs.macros.entry++] = data;
}
void Maxwell3D::ProcessFirmwareCall4() {
@@ -452,11 +449,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.shadow_scratch[0] = 1;
regs.reg_array[0xd00] = 1;
}
void Maxwell3D::StampQueryResult(u64 payload, bool long_query) {
const GPUVAddr sequence_address{regs.report_semaphore.Address()};
const GPUVAddr sequence_address{regs.query.QueryAddress()};
if (long_query) {
memory_manager.Write<u64>(sequence_address + sizeof(u64), system.GPU().GetTicks());
memory_manager.Write<u64>(sequence_address, payload);
@@ -467,17 +464,15 @@ void Maxwell3D::StampQueryResult(u64 payload, bool long_query) {
void Maxwell3D::ProcessQueryGet() {
// TODO(Subv): Support the other query units.
if (regs.report_semaphore.query.location != Regs::ReportSemaphore::Location::All) {
LOG_DEBUG(HW_GPU, "Locations other than ALL are unimplemented");
if (regs.query.query_get.unit != Regs::QueryUnit::Crop) {
LOG_DEBUG(HW_GPU, "Units other than CROP are unimplemented");
}
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;
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;
std::function<void()> operation([this, sequence_address, payload] {
memory_manager.Write<u32>(sequence_address, payload);
});
@@ -487,8 +482,8 @@ void Maxwell3D::ProcessQueryGet() {
u64_le value;
u64_le timestamp;
};
const GPUVAddr sequence_address{regs.report_semaphore.Address()};
const u32 payload = regs.report_semaphore.payload;
const GPUVAddr sequence_address{regs.query.QueryAddress()};
const u32 payload = regs.query.query_sequence;
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);
@@ -496,19 +491,19 @@ void Maxwell3D::ProcessQueryGet() {
rasterizer->SyncOperation(std::move(operation));
}
break;
case Regs::ReportSemaphore::Operation::Acquire:
case Regs::QueryOperation::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::ReportSemaphore::Operation::ReportOnly:
case Regs::QueryOperation::Counter:
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.report_semaphore.query.short_query == 0);
StampQueryResult(*result, regs.query.query_get.short_query == 0);
}
break;
case Regs::ReportSemaphore::Operation::Trap:
case Regs::QueryOperation::Trap:
UNIMPLEMENTED_MSG("Unimplemented query operation TRAP");
break;
default:
@@ -518,31 +513,31 @@ void Maxwell3D::ProcessQueryGet() {
}
void Maxwell3D::ProcessQueryCondition() {
const GPUVAddr condition_address{regs.render_enable.Address()};
switch (regs.render_enable.mode) {
case Regs::RenderEnable::Mode::True: {
const GPUVAddr condition_address{regs.condition.Address()};
switch (regs.condition.mode) {
case Regs::ConditionMode::Always: {
execute_on = true;
break;
}
case Regs::RenderEnable::Mode::False: {
case Regs::ConditionMode::Never: {
execute_on = false;
break;
}
case Regs::RenderEnable::Mode::Conditional: {
Regs::ReportSemaphore::Compare cmp;
case Regs::ConditionMode::ResNonZero: {
Regs::QueryCompare cmp;
memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
execute_on = cmp.initial_sequence != 0U && cmp.initial_mode != 0U;
break;
}
case Regs::RenderEnable::Mode::IfEqual: {
Regs::ReportSemaphore::Compare cmp;
case Regs::ConditionMode::Equal: {
Regs::QueryCompare 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::RenderEnable::Mode::IfNotEqual: {
Regs::ReportSemaphore::Compare cmp;
case Regs::ConditionMode::NotEqual: {
Regs::QueryCompare cmp;
memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
execute_on =
cmp.initial_sequence != cmp.current_sequence || cmp.initial_mode != cmp.current_mode;
@@ -557,21 +552,21 @@ void Maxwell3D::ProcessQueryCondition() {
}
void Maxwell3D::ProcessCounterReset() {
switch (regs.clear_report_value) {
case Regs::ClearReport::ZPassPixelCount:
switch (regs.counter_reset) {
case Regs::CounterReset::SampleCnt:
rasterizer->ResetCounter(QueryType::SamplesPassed);
break;
default:
LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}", regs.clear_report_value);
LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}", regs.counter_reset);
break;
}
}
void Maxwell3D::ProcessSyncPoint() {
const u32 sync_point = regs.sync_info.sync_point.Value();
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) {
const u32 increment = regs.sync_info.increment.Value();
[[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value();
if (increment) {
rasterizer->SignalSyncPoint(sync_point);
}
}
@@ -579,24 +574,23 @@ 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_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?");
ASSERT_MSG(!(regs.index_array.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_id == Maxwell3D::Regs::Draw::InstanceId::First ||
regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
ASSERT_MSG(!regs.draw.instance_next || !regs.draw.instance_cont,
"Illegal combination of instancing parameters");
ProcessTopologyOverride();
if (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) {
if (regs.draw.instance_next) {
// Increment the current instance *before* drawing.
state.current_instance++;
} else if (regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged) {
state.current_instance += 1;
} else if (!regs.draw.instance_cont) {
// Reset the current instance to 0.
state.current_instance = 0;
}
const bool is_indexed{regs.index_buffer.count && !regs.vertex_buffer.count};
const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count};
if (ShouldExecute()) {
rasterizer->Draw(is_indexed, false);
}
@@ -606,60 +600,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_buffer.count = 0;
regs.index_array.count = 0;
} else {
regs.vertex_buffer.count = 0;
}
}
std::optional<u64> Maxwell3D::GetQueryResult() {
switch (regs.report_semaphore.query.report) {
case Regs::ReportSemaphore::Report::Payload:
return regs.report_semaphore.payload;
case Regs::ReportSemaphore::Report::ZPassPixelCount64:
switch (regs.query.query_get.select) {
case Regs::QuerySelect::Payload:
return regs.query.query_sequence;
case Regs::QuerySelect::SamplesPassed:
// Deferred.
rasterizer->Query(regs.report_semaphore.Address(), QueryType::SamplesPassed,
rasterizer->Query(regs.query.QueryAddress(), QueryType::SamplesPassed,
system.GPU().GetTicks());
return std::nullopt;
default:
LOG_DEBUG(HW_GPU, "Unimplemented query report type {}",
regs.report_semaphore.query.report.Value());
LOG_DEBUG(HW_GPU, "Unimplemented query select type {}",
regs.query.query_get.select.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.bind_groups[stage_index];
auto& buffer = state.shader_stages[stage_index].const_buffers[bind_data.shader_slot];
const auto& bind_data = regs.cb_bind[stage_index];
auto& buffer = state.shader_stages[stage_index].const_buffers[bind_data.index];
buffer.enabled = bind_data.valid.Value() != 0;
buffer.address = regs.const_buffer.Address();
buffer.size = regs.const_buffer.size;
buffer.address = regs.const_buffer.BufferAddress();
buffer.size = regs.const_buffer.cb_size;
const bool is_enabled = bind_data.valid.Value() != 0;
if (!is_enabled) {
rasterizer->DisableGraphicsUniformBuffer(stage_index, bind_data.shader_slot);
rasterizer->DisableGraphicsUniformBuffer(stage_index, bind_data.index);
return;
}
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);
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);
}
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.Address();
const GPUVAddr buffer_address = regs.const_buffer.BufferAddress();
ASSERT(buffer_address != 0);
// Don't allow writing past the end of the buffer.
ASSERT(regs.const_buffer.offset <= regs.const_buffer.size);
ASSERT(regs.const_buffer.cb_pos <= regs.const_buffer.cb_size);
const GPUVAddr address{buffer_address + regs.const_buffer.offset};
const GPUVAddr address{buffer_address + regs.const_buffer.cb_pos};
const size_t copy_size = amount * sizeof(u32);
memory_manager.WriteBlock(address, start_base, copy_size);
// Increment the current buffer position.
regs.const_buffer.offset += static_cast<u32>(copy_size);
regs.const_buffer.cb_pos += static_cast<u32>(copy_size);
}
void Maxwell3D::ProcessCBData(u32 value) {
@@ -667,8 +661,7 @@ void Maxwell3D::ProcessCBData(u32 value) {
}
Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
const GPUVAddr tic_address_gpu{regs.tex_header.Address() +
tic_index * sizeof(Texture::TICEntry)};
const GPUVAddr tic_address_gpu{regs.tic.Address() + tic_index * sizeof(Texture::TICEntry)};
Texture::TICEntry tic_entry;
memory_manager.ReadBlockUnsafe(tic_address_gpu, &tic_entry, sizeof(Texture::TICEntry));
@@ -677,8 +670,7 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
}
Texture::TSCEntry Maxwell3D::GetTSCEntry(u32 tsc_index) const {
const GPUVAddr tsc_address_gpu{regs.tex_sampler.Address() +
tsc_index * sizeof(Texture::TSCEntry)};
const GPUVAddr tsc_address_gpu{regs.tsc.Address() + tsc_index * sizeof(Texture::TSCEntry)};
Texture::TSCEntry tsc_entry;
memory_manager.ReadBlockUnsafe(tsc_address_gpu, &tsc_entry, sizeof(Texture::TSCEntry));

File diff suppressed because it is too large Load Diff

View File

@@ -24,15 +24,11 @@ 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,
@@ -42,8 +38,8 @@ enum class RenderTargetFormat : u32 {
R32G32_SINT = 0xCC,
R32G32_UINT = 0xCD,
R16G16B16X16_FLOAT = 0xCE,
A8R8G8B8_UNORM = 0xCF,
A8R8G8B8_SRGB = 0xD0,
B8G8R8A8_UNORM = 0xCF,
B8G8R8A8_SRGB = 0xD0,
A2B10G10R10_UNORM = 0xD1,
A2B10G10R10_UINT = 0xD2,
A8B8G8R8_UNORM = 0xD5,
@@ -56,13 +52,10 @@ 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,
@@ -78,42 +71,17 @@ 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 {
Z32_FLOAT = 0xA,
Z16_UNORM = 0x13,
Z24_UNORM_S8_UINT = 0x14,
X8Z24_UNORM = 0x15,
S8Z24_UNORM = 0x16,
D32_FLOAT = 0xA,
D16_UNORM = 0x13,
S8_UINT_Z24_UNORM = 0x14,
D24X8_UNORM = 0x15,
D24S8_UNORM = 0x16,
S8_UINT = 0x17,
V8Z24_UNORM = 0x18,
Z32_FLOAT_X24S8_UINT = 0x19,
/*
X8Z24_UNORM_X16V8S8_UINT = 0x1D,
Z32_FLOAT_X16V8X8_UINT = 0x1E,
Z32_FLOAT_X16V8S8_UINT = 0x1F,
*/
D24C8_UNORM = 0x18,
D32_FLOAT_S8X24_UINT = 0x19,
};
namespace Engines {

View File

@@ -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.global_base_instance_index = parameters[5];
maxwell3d.regs.vb_base_instance = parameters[5];
maxwell3d.mme_draw.instance_count = instance_count;
maxwell3d.regs.global_base_vertex_index = parameters[3];
maxwell3d.regs.index_buffer.count = parameters[1];
maxwell3d.regs.index_buffer.first = parameters[4];
maxwell3d.regs.vb_element_base = parameters[3];
maxwell3d.regs.index_array.count = parameters[1];
maxwell3d.regs.index_array.first = parameters[4];
if (maxwell3d.ShouldExecute()) {
maxwell3d.Rasterizer().Draw(true, true);
}
maxwell3d.regs.index_buffer.count = 0;
maxwell3d.regs.index_array.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.global_base_instance_index = parameters[4];
maxwell3d.regs.vb_base_instance = 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_buffer.first = parameters[3];
maxwell3d.regs.vertex_id_base = element_base;
maxwell3d.regs.index_buffer.count = parameters[1];
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.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
maxwell3d.regs.global_base_vertex_index = element_base;
maxwell3d.regs.global_base_instance_index = base_instance;
maxwell3d.regs.vb_element_base = element_base;
maxwell3d.regs.vb_base_instance = 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.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.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.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.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.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.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_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.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.mme_draw.instance_count = instance_count;
maxwell3d.CallMethodFromMME(0x8e3, 0x640);
maxwell3d.CallMethodFromMME(0x8e4, base_vertex);

View File

@@ -137,7 +137,7 @@ public:
std::unique_lock lock{mutex};
if (maxwell3d) {
const auto& regs = maxwell3d->regs;
Stream(VideoCore::QueryType::SamplesPassed).Update(regs.zpass_pixel_count_enable);
Stream(VideoCore::QueryType::SamplesPassed).Update(regs.samplecnt_enable);
}
}

View File

@@ -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(u32 location) {
const auto index = location / 4;
std::pair<GLint, GLint> TransformFeedbackEnum(u8 location) {
const u8 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_binding == Maxwell::SamplerBinding::ViaHeaderBinding};
const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex};
const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
const Shader::Info& info{stage_infos[stage]};
buffer_cache.UnbindGraphicsStorageBuffers(stage);
@@ -557,25 +557,10 @@ void GraphicsPipeline::GenerateTransformFeedbackState() {
++current_stream;
const auto& locations = key.xfb_state.varyings[feedback];
std::optional<u32> current_index;
std::optional<u8> current_index;
for (u32 offset = 0; offset < layout.varying_count; ++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;
};
const auto attribute{get_attribute(offset)};
const auto index = attribute / 4U;
const u8 location = locations[offset];
const u8 index = location / 4;
if (current_index == index) {
// Increase number of components of the previous attachment
@@ -584,7 +569,7 @@ void GraphicsPipeline::GenerateTransformFeedbackState() {
}
current_index = index;
std::tie(cursor[0], cursor[2]) = TransformFeedbackEnum(attribute);
std::tie(cursor[0], cursor[2]) = TransformFeedbackEnum(location);
cursor[1] = 1;
cursor += XFB_ENTRY_STRIDE;
}

View File

@@ -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::Tessellation::DomainType> tessellation_primitive;
BitField<8, 2, Maxwell::Tessellation::Spacing> tessellation_spacing;
BitField<6, 2, Maxwell::TessellationPrimitive> tessellation_primitive;
BitField<8, 2, Maxwell::TessellationSpacing> tessellation_spacing;
BitField<10, 1, u32> tessellation_clockwise;
};
std::array<u32, 3> padding;

View File

@@ -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::SInt ||
attrib.type == Maxwell::VertexAttribute::Type::UInt) {
if (attrib.type == Maxwell::VertexAttribute::Type::SignedInt ||
attrib.type == Maxwell::VertexAttribute::Type::UnsignedInt) {
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.vertex_stream_instances.IsInstancingEnabled(gl_index);
const GLuint divisor = instancing_enabled ? regs.vertex_streams[index].frequency : 0;
const bool instancing_enabled = regs.instanced_arrays.IsInstancingEnabled(gl_index);
const GLuint divisor = instancing_enabled ? regs.vertex_array[index].divisor : 0;
glVertexBindingDivisor(gl_index, divisor);
}
}
@@ -147,27 +147,27 @@ void RasterizerOpenGL::Clear() {
bool use_depth{};
bool use_stencil{};
if (regs.clear_surface.R || regs.clear_surface.G || regs.clear_surface.B ||
regs.clear_surface.A) {
if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
regs.clear_buffers.A) {
use_color = true;
const GLuint index = regs.clear_surface.RT;
const GLuint index = regs.clear_buffers.RT;
state_tracker.NotifyColorMask(index);
glColorMaski(index, regs.clear_surface.R != 0, regs.clear_surface.G != 0,
regs.clear_surface.B != 0, regs.clear_surface.A != 0);
glColorMaski(index, regs.clear_buffers.R != 0, regs.clear_buffers.G != 0,
regs.clear_buffers.B != 0, regs.clear_buffers.A != 0);
// TODO(Rodrigo): Determine if clamping is used on clears
SyncFragmentColorClampState();
SyncFramebufferSRGB();
}
if (regs.clear_surface.Z) {
if (regs.clear_buffers.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_surface.S) {
if (regs.clear_buffers.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_control.use_scissor) {
if (regs.clear_flags.scissor) {
SyncScissorTest();
} else {
state_tracker.NotifyScissor0();
glDisablei(GL_SCISSOR_TEST, 0);
}
UNIMPLEMENTED_IF(regs.clear_control.use_viewport_clip0);
UNIMPLEMENTED_IF(regs.clear_flags.viewport);
if (use_color) {
glClearBufferfv(GL_COLOR, regs.clear_surface.RT, regs.clear_color.data());
glClearBufferfv(GL_COLOR, regs.clear_buffers.RT, regs.clear_color);
}
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.global_base_instance_index);
const GLuint base_instance = static_cast<GLuint>(maxwell3d->regs.vb_base_instance);
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.global_base_vertex_index);
const GLsizei num_vertices = static_cast<GLsizei>(maxwell3d->regs.index_buffer.count);
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 GLvoid* const offset = buffer_cache_runtime.IndexOffset();
const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format);
const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_array.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.gl_front_face);
GLenum mode = MaxwellToGL::FrontFace(regs.front_face);
bool flip_faces = true;
if (regs.window_origin.flip_y != 0) {
if (regs.screen_y_control.triangle_rast_flip != 0) {
flip_faces = !flip_faces;
}
if (regs.viewport_transform[0].scale_y < 0.0f) {
@@ -582,15 +582,14 @@ void RasterizerOpenGL::SyncViewport() {
if (regs.viewport_transform[0].scale_y < 0.0f) {
flip_y = !flip_y;
}
const bool lower_left{regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft};
if (lower_left) {
if (regs.screen_y_control.y_negate != 0) {
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(lower_left);
state_tracker.SetYNegate(regs.screen_y_control.y_negate != 0);
}
const bool is_rescaling{texture_cache.IsRescaling()};
const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f;
@@ -658,8 +657,7 @@ void RasterizerOpenGL::SyncDepthClamp() {
}
flags[Dirty::DepthClampEnabled] = false;
oglEnable(GL_DEPTH_CLAMP, maxwell3d->regs.viewport_clip_control.geometry_clip !=
Maxwell::ViewportClipControl::GeometryClip::Passthrough);
oglEnable(GL_DEPTH_CLAMP, maxwell3d->regs.view_volume_clip_control.depth_clamp_disabled == 0);
}
void RasterizerOpenGL::SyncClipEnabled(u32 clip_mask) {
@@ -669,7 +667,7 @@ void RasterizerOpenGL::SyncClipEnabled(u32 clip_mask) {
}
flags[Dirty::ClipDistances] = false;
clip_mask &= maxwell3d->regs.user_clip_enable.raw;
clip_mask &= maxwell3d->regs.clip_distance_enabled;
if (clip_mask == last_clip_distance_mask) {
return;
}
@@ -691,9 +689,9 @@ void RasterizerOpenGL::SyncCullMode() {
if (flags[Dirty::CullTest]) {
flags[Dirty::CullTest] = false;
if (regs.gl_cull_test_enabled) {
if (regs.cull_test_enabled) {
glEnable(GL_CULL_FACE);
glCullFace(MaxwellToGL::CullFace(regs.gl_cull_face));
glCullFace(MaxwellToGL::CullFace(regs.cull_face));
} else {
glDisable(GL_CULL_FACE);
}
@@ -745,20 +743,20 @@ void RasterizerOpenGL::SyncStencilTestState() {
const auto& regs = maxwell3d->regs;
oglEnable(GL_STENCIL_TEST, regs.stencil_enable);
glStencilFuncSeparate(GL_FRONT, MaxwellToGL::ComparisonOp(regs.stencil_front_op.func),
regs.stencil_front_func.ref, regs.stencil_front_func.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_func.mask);
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));
glStencilMaskSeparate(GL_FRONT, regs.stencil_front_mask);
if (regs.stencil_two_side_enable) {
glStencilFuncSeparate(GL_BACK, MaxwellToGL::ComparisonOp(regs.stencil_back_op.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));
glStencilMaskSeparate(GL_BACK, regs.stencil_back_func.mask);
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));
glStencilMaskSeparate(GL_BACK, regs.stencil_back_mask);
} else {
glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 0xFFFFFFFF);
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
@@ -784,7 +782,7 @@ void RasterizerOpenGL::SyncPolygonModes() {
flags[Dirty::PolygonModes] = false;
const auto& regs = maxwell3d->regs;
if (regs.fill_via_triangle_mode != Maxwell::FillViaTriangleMode::Disabled) {
if (regs.fill_rectangle) {
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);
@@ -857,8 +855,8 @@ void RasterizerOpenGL::SyncMultiSampleState() {
flags[Dirty::MultisampleControl] = false;
const auto& regs = maxwell3d->regs;
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);
oglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE, regs.multisample_control.alpha_to_coverage);
oglEnable(GL_SAMPLE_ALPHA_TO_ONE, regs.multisample_control.alpha_to_one);
}
void RasterizerOpenGL::SyncFragmentColorClampState() {
@@ -868,8 +866,7 @@ void RasterizerOpenGL::SyncFragmentColorClampState() {
}
flags[Dirty::FragmentClampColor] = false;
glClampColor(GL_CLAMP_FRAGMENT_COLOR,
maxwell3d->regs.frag_color_clamp.AnyEnabled() ? GL_TRUE : GL_FALSE);
glClampColor(GL_CLAMP_FRAGMENT_COLOR, maxwell3d->regs.frag_color_clamp ? GL_TRUE : GL_FALSE);
}
void RasterizerOpenGL::SyncBlendState() {
@@ -889,18 +886,18 @@ void RasterizerOpenGL::SyncBlendState() {
}
flags[Dirty::BlendStates] = false;
if (!regs.blend_per_target_enabled) {
if (!regs.independent_blend_enable) {
if (!regs.blend.enable[0]) {
glDisable(GL_BLEND);
return;
}
glEnable(GL_BLEND);
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));
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));
return;
}
@@ -919,13 +916,14 @@ void RasterizerOpenGL::SyncBlendState() {
}
glEnablei(GL_BLEND, static_cast<GLuint>(i));
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));
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));
}
}
@@ -939,7 +937,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.op));
glLogicOp(MaxwellToGL::LogicOp(regs.logic_op.operation));
} else {
glDisable(GL_COLOR_LOGIC_OP);
}
@@ -998,7 +996,7 @@ void RasterizerOpenGL::SyncPointState() {
flags[Dirty::PointSize] = false;
oglEnable(GL_POINT_SPRITE, maxwell3d->regs.point_sprite_enable);
oglEnable(GL_PROGRAM_POINT_SIZE, maxwell3d->regs.point_size_attribute.enabled);
oglEnable(GL_PROGRAM_POINT_SIZE, maxwell3d->regs.vp_point_size.enable);
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));
@@ -1012,8 +1010,8 @@ void RasterizerOpenGL::SyncLineState() {
flags[Dirty::LineWidth] = false;
const auto& regs = maxwell3d->regs;
oglEnable(GL_LINE_SMOOTH, regs.line_anti_alias_enable);
glLineWidth(regs.line_anti_alias_enable ? regs.line_width_smooth : regs.line_width_aliased);
oglEnable(GL_LINE_SMOOTH, regs.line_smooth_enable);
glLineWidth(regs.line_smooth_enable ? regs.line_width_smooth : regs.line_width_aliased);
}
void RasterizerOpenGL::SyncPolygonOffset() {
@@ -1031,8 +1029,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.slope_scale_depth_bias, regs.depth_bias / 2.0f,
regs.depth_bias_clamp);
glPolygonOffsetClamp(regs.polygon_offset_factor, regs.polygon_offset_units / 2.0f,
regs.polygon_offset_clamp);
}
}
@@ -1064,14 +1062,14 @@ void RasterizerOpenGL::SyncFramebufferSRGB() {
void RasterizerOpenGL::BeginTransformFeedback(GraphicsPipeline* program, GLenum primitive_mode) {
const auto& regs = maxwell3d->regs;
if (regs.transform_feedback_enabled == 0) {
if (regs.tfb_enabled == 0) {
return;
}
program->ConfigureTransformFeedback();
UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderType::TessellationInit) ||
regs.IsShaderConfigEnabled(Maxwell::ShaderType::Tessellation) ||
regs.IsShaderConfigEnabled(Maxwell::ShaderType::Geometry));
UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationControl) ||
regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationEval) ||
regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::Geometry));
UNIMPLEMENTED_IF(primitive_mode != GL_POINTS);
// We may have to call BeginTransformFeedbackNV here since they seem to call different
@@ -1082,7 +1080,7 @@ void RasterizerOpenGL::BeginTransformFeedback(GraphicsPipeline* program, GLenum
}
void RasterizerOpenGL::EndTransformFeedback() {
if (maxwell3d->regs.transform_feedback_enabled != 0) {
if (maxwell3d->regs.tfb_enabled != 0) {
glEndTransformFeedback();
}
}

View File

@@ -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::Tessellation::DomainType::Isolines:
case Maxwell::TessellationPrimitive::Isolines:
return Shader::TessPrimitive::Isolines;
case Maxwell::Tessellation::DomainType::Triangles:
case Maxwell::TessellationPrimitive::Triangles:
return Shader::TessPrimitive::Triangles;
case Maxwell::Tessellation::DomainType::Quads:
case Maxwell::TessellationPrimitive::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::Tessellation::Spacing::Integer:
case Maxwell::TessellationSpacing::Equal:
return Shader::TessSpacing::Equal;
case Maxwell::Tessellation::Spacing::FractionalOdd:
case Maxwell::TessellationSpacing::FractionalOdd:
return Shader::TessSpacing::FractionalOdd;
case Maxwell::Tessellation::Spacing::FractionalEven:
case Maxwell::TessellationSpacing::FractionalEven:
return Shader::TessSpacing::FractionalEven;
}
ASSERT(false);
@@ -139,15 +139,14 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
}
void SetXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs) {
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;
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;
}
} // Anonymous namespace
@@ -310,16 +309,14 @@ GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() {
}
const auto& regs{maxwell3d->regs};
graphics_key.raw = 0;
graphics_key.early_z.Assign(regs.mandated_early_z != 0 ? 1 : 0);
graphics_key.early_z.Assign(regs.force_early_fragment_tests != 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.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);
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);
if (graphics_key.xfb_enabled) {
SetXfbState(graphics_key.xfb_state, regs);
}
@@ -357,7 +354,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_buffer.count <= 6 || maxwell3d->regs.vertex_buffer.count <= 6) {
if (maxwell3d->regs.index_array.count <= 6 || maxwell3d->regs.vertex_buffer.count <= 6) {
return pipeline;
}
return nullptr;

View File

@@ -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_streams) + i * NUM(vertex_streams[0]);
const std::size_t array_offset = OFF(vertex_array) + i * NUM(vertex_array[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(vertex_stream_instances) + i;
const std::size_t instance_offset = OFF(instanced_arrays) + 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_scale_offset_enbled)] = ViewportTransform;
tables[1][OFF(viewport_scale_offset_enbled)] = Viewports;
tables[0][OFF(viewport_transform_enabled)] = ViewportTransform;
tables[1][OFF(viewport_transform_enabled)] = 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_via_triangle_mode)] = PolygonModes;
tables[0][OFF(fill_rectangle)] = PolygonModes;
}
void SetupDirtyDepthTest(Tables& tables) {
@@ -100,14 +100,12 @@ void SetupDirtyDepthTest(Tables& tables) {
void SetupDirtyStencilTest(Tables& tables) {
static constexpr std::array offsets = {
OFF(stencil_enable), OFF(stencil_front_op.func),
OFF(stencil_front_func.ref), OFF(stencil_front_func.func_mask),
OFF(stencil_front_op.fail), OFF(stencil_front_op.zfail),
OFF(stencil_front_op.zpass), OFF(stencil_front_func.mask),
OFF(stencil_two_side_enable), OFF(stencil_back_op.func),
OFF(stencil_back_func.ref), OFF(stencil_back_func.func_mask),
OFF(stencil_back_op.fail), OFF(stencil_back_op.zfail),
OFF(stencil_back_op.zpass), OFF(stencil_back_func.mask)};
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_back_mask)};
for (const auto offset : offsets) {
tables[0][offset] = StencilTest;
}
@@ -123,15 +121,15 @@ void SetupDirtyAlphaTest(Tables& tables) {
void SetupDirtyBlend(Tables& tables) {
FillBlock(tables[0], OFF(blend_color), NUM(blend_color), BlendColor);
tables[0][OFF(blend_per_target_enabled)] = BlendIndependentEnabled;
tables[0][OFF(independent_blend_enable)] = BlendIndependentEnabled;
for (std::size_t i = 0; i < Regs::NumRenderTargets; ++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);
const std::size_t offset = OFF(independent_blend) + i * NUM(independent_blend[0]);
FillBlock(tables[0], offset, NUM(independent_blend[0]), BlendState0 + i);
tables[0][OFF(blend.enable) + i] = static_cast<u8>(BlendState0 + i);
}
FillBlock(tables[1], OFF(blend_per_target), NUM(blend_per_target), BlendStates);
FillBlock(tables[1], OFF(independent_blend), NUM(independent_blend), BlendStates);
FillBlock(tables[1], OFF(blend), NUM(blend), BlendStates);
}
@@ -144,14 +142,13 @@ 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(slope_scale_depth_bias)] = PolygonOffset;
table[OFF(depth_bias)] = PolygonOffset;
table[OFF(depth_bias_clamp)] = PolygonOffset;
table[OFF(polygon_offset_factor)] = PolygonOffset;
table[OFF(polygon_offset_units)] = PolygonOffset;
table[OFF(polygon_offset_clamp)] = PolygonOffset;
}
void SetupDirtyMultisampleControl(Tables& tables) {
FillBlock(tables[0], OFF(anti_alias_alpha_control), NUM(anti_alias_alpha_control),
MultisampleControl);
FillBlock(tables[0], OFF(multisample_control), NUM(multisample_control), MultisampleControl);
}
void SetupDirtyRasterizeEnable(Tables& tables) {
@@ -171,7 +168,7 @@ void SetupDirtyFragmentClampColor(Tables& tables) {
}
void SetupDirtyPointSize(Tables& tables) {
tables[0][OFF(point_size_attribute)] = PointSize;
tables[0][OFF(vp_point_size)] = PointSize;
tables[0][OFF(point_size)] = PointSize;
tables[0][OFF(point_sprite_enable)] = PointSize;
}
@@ -179,28 +176,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_anti_alias_enable)] = LineWidth;
tables[0][OFF(line_smooth_enable)] = LineWidth;
}
void SetupDirtyClipControl(Tables& tables) {
auto& table = tables[0];
table[OFF(window_origin)] = ClipControl;
table[OFF(screen_y_control)] = ClipControl;
table[OFF(depth_mode)] = ClipControl;
}
void SetupDirtyDepthClampEnabled(Tables& tables) {
tables[0][OFF(viewport_clip_control)] = DepthClampEnabled;
tables[0][OFF(view_volume_clip_control)] = DepthClampEnabled;
}
void SetupDirtyMisc(Tables& tables) {
auto& table = tables[0];
table[OFF(user_clip_enable)] = ClipDistances;
table[OFF(clip_distance_enabled)] = ClipDistances;
table[OFF(gl_front_face)] = FrontFace;
table[OFF(front_face)] = FrontFace;
table[OFF(gl_cull_test_enabled)] = CullTest;
table[OFF(gl_cull_face)] = CullTest;
table[OFF(cull_test_enabled)] = CullTest;
table[OFF(cull_face)] = CullTest;
}
} // Anonymous namespace

View File

@@ -126,60 +126,51 @@ inline const FormatTuple& GetFormatTuple(VideoCore::Surface::PixelFormat pixel_f
inline GLenum VertexFormat(Maxwell::VertexAttribute attrib) {
switch (attrib.type) {
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:
case Maxwell::VertexAttribute::Type::UnsignedNorm:
case Maxwell::VertexAttribute::Type::UnsignedScaled:
case Maxwell::VertexAttribute::Type::UnsignedInt:
switch (attrib.size) {
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:
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:
return GL_UNSIGNED_BYTE;
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:
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:
return GL_UNSIGNED_SHORT;
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:
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:
return GL_UNSIGNED_INT;
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
return GL_UNSIGNED_INT_2_10_10_10_REV;
default:
break;
}
break;
case Maxwell::VertexAttribute::Type::SNorm:
case Maxwell::VertexAttribute::Type::SScaled:
case Maxwell::VertexAttribute::Type::SInt:
case Maxwell::VertexAttribute::Type::SignedNorm:
case Maxwell::VertexAttribute::Type::SignedScaled:
case Maxwell::VertexAttribute::Type::SignedInt:
switch (attrib.size) {
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:
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:
return GL_BYTE;
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:
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:
return GL_SHORT;
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:
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:
return GL_INT;
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
return GL_INT_2_10_10_10_REV;
default:
break;
@@ -187,17 +178,17 @@ inline GLenum VertexFormat(Maxwell::VertexAttribute attrib) {
break;
case Maxwell::VertexAttribute::Type::Float:
switch (attrib.size) {
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:
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:
return GL_HALF_FLOAT;
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:
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:
return GL_FLOAT;
case Maxwell::VertexAttribute::Size::Size_B10_G11_R11:
case Maxwell::VertexAttribute::Size::Size_11_11_10:
return GL_UNSIGNED_INT_10F_11F_11F_REV;
default:
break;
@@ -344,20 +335,20 @@ inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) {
inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
switch (equation) {
case Maxwell::Blend::Equation::Add_D3D:
case Maxwell::Blend::Equation::Add_GL:
case Maxwell::Blend::Equation::Add:
case Maxwell::Blend::Equation::AddGL:
return GL_FUNC_ADD;
case Maxwell::Blend::Equation::Subtract_D3D:
case Maxwell::Blend::Equation::Subtract_GL:
case Maxwell::Blend::Equation::Subtract:
case Maxwell::Blend::Equation::SubtractGL:
return GL_FUNC_SUBTRACT;
case Maxwell::Blend::Equation::ReverseSubtract_D3D:
case Maxwell::Blend::Equation::ReverseSubtract_GL:
case Maxwell::Blend::Equation::ReverseSubtract:
case Maxwell::Blend::Equation::ReverseSubtractGL:
return GL_FUNC_REVERSE_SUBTRACT;
case Maxwell::Blend::Equation::Min_D3D:
case Maxwell::Blend::Equation::Min_GL:
case Maxwell::Blend::Equation::Min:
case Maxwell::Blend::Equation::MinGL:
return GL_MIN;
case Maxwell::Blend::Equation::Max_D3D:
case Maxwell::Blend::Equation::Max_GL:
case Maxwell::Blend::Equation::Max:
case Maxwell::Blend::Equation::MaxGL:
return GL_MAX;
}
UNIMPLEMENTED_MSG("Unimplemented blend equation={}", equation);
@@ -366,62 +357,62 @@ inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
switch (factor) {
case Maxwell::Blend::Factor::Zero_D3D:
case Maxwell::Blend::Factor::Zero_GL:
case Maxwell::Blend::Factor::Zero:
case Maxwell::Blend::Factor::ZeroGL:
return GL_ZERO;
case Maxwell::Blend::Factor::One_D3D:
case Maxwell::Blend::Factor::One_GL:
case Maxwell::Blend::Factor::One:
case Maxwell::Blend::Factor::OneGL:
return GL_ONE;
case Maxwell::Blend::Factor::SourceColor_D3D:
case Maxwell::Blend::Factor::SourceColor_GL:
case Maxwell::Blend::Factor::SourceColor:
case Maxwell::Blend::Factor::SourceColorGL:
return GL_SRC_COLOR;
case Maxwell::Blend::Factor::OneMinusSourceColor_D3D:
case Maxwell::Blend::Factor::OneMinusSourceColor_GL:
case Maxwell::Blend::Factor::OneMinusSourceColor:
case Maxwell::Blend::Factor::OneMinusSourceColorGL:
return GL_ONE_MINUS_SRC_COLOR;
case Maxwell::Blend::Factor::SourceAlpha_D3D:
case Maxwell::Blend::Factor::SourceAlpha_GL:
case Maxwell::Blend::Factor::SourceAlpha:
case Maxwell::Blend::Factor::SourceAlphaGL:
return GL_SRC_ALPHA;
case Maxwell::Blend::Factor::OneMinusSourceAlpha_D3D:
case Maxwell::Blend::Factor::OneMinusSourceAlpha_GL:
case Maxwell::Blend::Factor::OneMinusSourceAlpha:
case Maxwell::Blend::Factor::OneMinusSourceAlphaGL:
return GL_ONE_MINUS_SRC_ALPHA;
case Maxwell::Blend::Factor::DestAlpha_D3D:
case Maxwell::Blend::Factor::DestAlpha_GL:
case Maxwell::Blend::Factor::DestAlpha:
case Maxwell::Blend::Factor::DestAlphaGL:
return GL_DST_ALPHA;
case Maxwell::Blend::Factor::OneMinusDestAlpha_D3D:
case Maxwell::Blend::Factor::OneMinusDestAlpha_GL:
case Maxwell::Blend::Factor::OneMinusDestAlpha:
case Maxwell::Blend::Factor::OneMinusDestAlphaGL:
return GL_ONE_MINUS_DST_ALPHA;
case Maxwell::Blend::Factor::DestColor_D3D:
case Maxwell::Blend::Factor::DestColor_GL:
case Maxwell::Blend::Factor::DestColor:
case Maxwell::Blend::Factor::DestColorGL:
return GL_DST_COLOR;
case Maxwell::Blend::Factor::OneMinusDestColor_D3D:
case Maxwell::Blend::Factor::OneMinusDestColor_GL:
case Maxwell::Blend::Factor::OneMinusDestColor:
case Maxwell::Blend::Factor::OneMinusDestColorGL:
return GL_ONE_MINUS_DST_COLOR;
case Maxwell::Blend::Factor::SourceAlphaSaturate_D3D:
case Maxwell::Blend::Factor::SourceAlphaSaturate_GL:
case Maxwell::Blend::Factor::SourceAlphaSaturate:
case Maxwell::Blend::Factor::SourceAlphaSaturateGL:
return GL_SRC_ALPHA_SATURATE;
case Maxwell::Blend::Factor::Source1Color_D3D:
case Maxwell::Blend::Factor::Source1Color_GL:
case Maxwell::Blend::Factor::Source1Color:
case Maxwell::Blend::Factor::Source1ColorGL:
return GL_SRC1_COLOR;
case Maxwell::Blend::Factor::OneMinusSource1Color_D3D:
case Maxwell::Blend::Factor::OneMinusSource1Color_GL:
case Maxwell::Blend::Factor::OneMinusSource1Color:
case Maxwell::Blend::Factor::OneMinusSource1ColorGL:
return GL_ONE_MINUS_SRC1_COLOR;
case Maxwell::Blend::Factor::Source1Alpha_D3D:
case Maxwell::Blend::Factor::Source1Alpha_GL:
case Maxwell::Blend::Factor::Source1Alpha:
case Maxwell::Blend::Factor::Source1AlphaGL:
return GL_SRC1_ALPHA;
case Maxwell::Blend::Factor::OneMinusSource1Alpha_D3D:
case Maxwell::Blend::Factor::OneMinusSource1Alpha_GL:
case Maxwell::Blend::Factor::OneMinusSource1Alpha:
case Maxwell::Blend::Factor::OneMinusSource1AlphaGL:
return GL_ONE_MINUS_SRC1_ALPHA;
case Maxwell::Blend::Factor::BlendFactor_D3D:
case Maxwell::Blend::Factor::ConstantColor_GL:
case Maxwell::Blend::Factor::ConstantColor:
case Maxwell::Blend::Factor::ConstantColorGL:
return GL_CONSTANT_COLOR;
case Maxwell::Blend::Factor::OneMinusBlendFactor_D3D:
case Maxwell::Blend::Factor::OneMinusConstantColor_GL:
case Maxwell::Blend::Factor::OneMinusConstantColor:
case Maxwell::Blend::Factor::OneMinusConstantColorGL:
return GL_ONE_MINUS_CONSTANT_COLOR;
case Maxwell::Blend::Factor::BothSourceAlpha_D3D:
case Maxwell::Blend::Factor::ConstantAlpha_GL:
case Maxwell::Blend::Factor::ConstantAlpha:
case Maxwell::Blend::Factor::ConstantAlphaGL:
return GL_CONSTANT_ALPHA;
case Maxwell::Blend::Factor::OneMinusBothSourceAlpha_D3D:
case Maxwell::Blend::Factor::OneMinusConstantAlpha_GL:
case Maxwell::Blend::Factor::OneMinusConstantAlpha:
case Maxwell::Blend::Factor::OneMinusConstantAlphaGL:
return GL_ONE_MINUS_CONSTANT_ALPHA;
}
UNIMPLEMENTED_MSG("Unimplemented blend factor={}", factor);
@@ -430,60 +421,60 @@ inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) {
switch (comparison) {
case Maxwell::ComparisonOp::Never_D3D:
case Maxwell::ComparisonOp::Never_GL:
case Maxwell::ComparisonOp::Never:
case Maxwell::ComparisonOp::NeverOld:
return GL_NEVER;
case Maxwell::ComparisonOp::Less_D3D:
case Maxwell::ComparisonOp::Less_GL:
case Maxwell::ComparisonOp::Less:
case Maxwell::ComparisonOp::LessOld:
return GL_LESS;
case Maxwell::ComparisonOp::Equal_D3D:
case Maxwell::ComparisonOp::Equal_GL:
case Maxwell::ComparisonOp::Equal:
case Maxwell::ComparisonOp::EqualOld:
return GL_EQUAL;
case Maxwell::ComparisonOp::LessEqual_D3D:
case Maxwell::ComparisonOp::LessEqual_GL:
case Maxwell::ComparisonOp::LessEqual:
case Maxwell::ComparisonOp::LessEqualOld:
return GL_LEQUAL;
case Maxwell::ComparisonOp::Greater_D3D:
case Maxwell::ComparisonOp::Greater_GL:
case Maxwell::ComparisonOp::Greater:
case Maxwell::ComparisonOp::GreaterOld:
return GL_GREATER;
case Maxwell::ComparisonOp::NotEqual_D3D:
case Maxwell::ComparisonOp::NotEqual_GL:
case Maxwell::ComparisonOp::NotEqual:
case Maxwell::ComparisonOp::NotEqualOld:
return GL_NOTEQUAL;
case Maxwell::ComparisonOp::GreaterEqual_D3D:
case Maxwell::ComparisonOp::GreaterEqual_GL:
case Maxwell::ComparisonOp::GreaterEqual:
case Maxwell::ComparisonOp::GreaterEqualOld:
return GL_GEQUAL;
case Maxwell::ComparisonOp::Always_D3D:
case Maxwell::ComparisonOp::Always_GL:
case Maxwell::ComparisonOp::Always:
case Maxwell::ComparisonOp::AlwaysOld:
return GL_ALWAYS;
}
UNIMPLEMENTED_MSG("Unimplemented comparison op={}", comparison);
return GL_ALWAYS;
}
inline GLenum StencilOp(Maxwell::StencilOp::Op stencil) {
inline GLenum StencilOp(Maxwell::StencilOp stencil) {
switch (stencil) {
case Maxwell::StencilOp::Op::Keep_D3D:
case Maxwell::StencilOp::Op::Keep_GL:
case Maxwell::StencilOp::Keep:
case Maxwell::StencilOp::KeepOGL:
return GL_KEEP;
case Maxwell::StencilOp::Op::Zero_D3D:
case Maxwell::StencilOp::Op::Zero_GL:
case Maxwell::StencilOp::Zero:
case Maxwell::StencilOp::ZeroOGL:
return GL_ZERO;
case Maxwell::StencilOp::Op::Replace_D3D:
case Maxwell::StencilOp::Op::Replace_GL:
case Maxwell::StencilOp::Replace:
case Maxwell::StencilOp::ReplaceOGL:
return GL_REPLACE;
case Maxwell::StencilOp::Op::IncrSaturate_D3D:
case Maxwell::StencilOp::Op::IncrSaturate_GL:
case Maxwell::StencilOp::Incr:
case Maxwell::StencilOp::IncrOGL:
return GL_INCR;
case Maxwell::StencilOp::Op::DecrSaturate_D3D:
case Maxwell::StencilOp::Op::DecrSaturate_GL:
case Maxwell::StencilOp::Decr:
case Maxwell::StencilOp::DecrOGL:
return GL_DECR;
case Maxwell::StencilOp::Op::Invert_D3D:
case Maxwell::StencilOp::Op::Invert_GL:
case Maxwell::StencilOp::Invert:
case Maxwell::StencilOp::InvertOGL:
return GL_INVERT;
case Maxwell::StencilOp::Op::Incr_D3D:
case Maxwell::StencilOp::Op::Incr_GL:
case Maxwell::StencilOp::IncrWrap:
case Maxwell::StencilOp::IncrWrapOGL:
return GL_INCR_WRAP;
case Maxwell::StencilOp::Op::Decr_D3D:
case Maxwell::StencilOp::Op::Decr_GL:
case Maxwell::StencilOp::DecrWrap:
case Maxwell::StencilOp::DecrWrapOGL:
return GL_DECR_WRAP;
}
UNIMPLEMENTED_MSG("Unimplemented stencil op={}", stencil);
@@ -514,39 +505,39 @@ inline GLenum CullFace(Maxwell::CullFace cull_face) {
return GL_BACK;
}
inline GLenum LogicOp(Maxwell::LogicOp::Op operation) {
inline GLenum LogicOp(Maxwell::LogicOperation operation) {
switch (operation) {
case Maxwell::LogicOp::Op::Clear:
case Maxwell::LogicOperation::Clear:
return GL_CLEAR;
case Maxwell::LogicOp::Op::And:
case Maxwell::LogicOperation::And:
return GL_AND;
case Maxwell::LogicOp::Op::AndReverse:
case Maxwell::LogicOperation::AndReverse:
return GL_AND_REVERSE;
case Maxwell::LogicOp::Op::Copy:
case Maxwell::LogicOperation::Copy:
return GL_COPY;
case Maxwell::LogicOp::Op::AndInverted:
case Maxwell::LogicOperation::AndInverted:
return GL_AND_INVERTED;
case Maxwell::LogicOp::Op::NoOp:
case Maxwell::LogicOperation::NoOp:
return GL_NOOP;
case Maxwell::LogicOp::Op::Xor:
case Maxwell::LogicOperation::Xor:
return GL_XOR;
case Maxwell::LogicOp::Op::Or:
case Maxwell::LogicOperation::Or:
return GL_OR;
case Maxwell::LogicOp::Op::Nor:
case Maxwell::LogicOperation::Nor:
return GL_NOR;
case Maxwell::LogicOp::Op::Equiv:
case Maxwell::LogicOperation::Equiv:
return GL_EQUIV;
case Maxwell::LogicOp::Op::Invert:
case Maxwell::LogicOperation::Invert:
return GL_INVERT;
case Maxwell::LogicOp::Op::OrReverse:
case Maxwell::LogicOperation::OrReverse:
return GL_OR_REVERSE;
case Maxwell::LogicOp::Op::CopyInverted:
case Maxwell::LogicOperation::CopyInverted:
return GL_COPY_INVERTED;
case Maxwell::LogicOp::Op::OrInverted:
case Maxwell::LogicOperation::OrInverted:
return GL_OR_INVERTED;
case Maxwell::LogicOp::Op::Nand:
case Maxwell::LogicOperation::Nand:
return GL_NAND;
case Maxwell::LogicOp::Op::Set:
case Maxwell::LogicOperation::Set:
return GL_SET;
}
UNIMPLEMENTED_MSG("Unimplemented logic operation={}", operation);

View File

@@ -34,15 +34,14 @@ constexpr std::array POLYGON_OFFSET_ENABLE_LUT = {
};
void RefreshXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs) {
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;
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;
}
} // Anonymous namespace
@@ -59,34 +58,33 @@ 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.transform_feedback_enabled != 0);
xfb_enabled.Assign(regs.tfb_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.viewport_clip_control.geometry_clip ==
Maxwell::ViewportClipControl::GeometryClip::Passthrough);
depth_clamp_disabled.Assign(regs.view_volume_clip_control.depth_clamp_disabled.Value());
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.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);
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());
logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0);
logic_op.Assign(PackLogicOp(regs.logic_op.op));
logic_op.Assign(PackLogicOp(regs.logic_op.operation));
topology.Assign(regs.draw.topology);
msaa_mode.Assign(regs.anti_alias_samples_mode);
msaa_mode.Assign(regs.multisample_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_GL;
regs.alpha_test_enabled != 0 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always;
alpha_test_func.Assign(PackComparisonOp(test_func));
early_z.Assign(regs.mandated_early_z != 0 ? 1 : 0);
early_z.Assign(regs.force_early_fragment_tests != 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.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);
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);
for (size_t i = 0; i < regs.rt.size(); ++i) {
color_formats[i] = static_cast<u8>(regs.rt[i].format);
@@ -118,8 +116,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.vertex_stream_instances.IsInstancingEnabled(index);
binding_divisors[index] = is_enabled ? regs.vertex_streams[index].frequency : 0;
const bool is_enabled = regs.instanced_arrays.IsInstancingEnabled(index);
binding_divisors[index] = is_enabled ? regs.vertex_array[index].divisor : 0;
enabled_divisors |= (is_enabled ? u64{1} : 0) << index;
}
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
@@ -166,17 +164,17 @@ void FixedPipelineState::BlendingAttachment::Refresh(const Maxwell& regs, size_t
// TODO: C++20 Use templated lambda to deduplicate code
if (!regs.blend_per_target_enabled) {
if (!regs.blend.enable[index]) {
if (!regs.independent_blend_enable) {
const auto& src = regs.blend;
if (!src.enable[index]) {
return;
}
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));
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));
enable.Assign(1);
return;
}
@@ -184,34 +182,34 @@ void FixedPipelineState::BlendingAttachment::Refresh(const Maxwell& regs, size_t
if (!regs.blend.enable[index]) {
return;
}
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));
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));
enable.Assign(1);
}
void FixedPipelineState::DynamicState::Refresh(const Maxwell& regs) {
u32 packed_front_face = PackFrontFace(regs.gl_front_face);
if (regs.window_origin.flip_y != 0) {
u32 packed_front_face = PackFrontFace(regs.front_face);
if (regs.screen_y_control.triangle_rast_flip != 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_op.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_func_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_op.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_func_func));
} else {
back.action_stencil_fail.Assign(front.action_stencil_fail);
back.action_depth_fail.Assign(front.action_depth_fail);
@@ -224,9 +222,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.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) {
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) {
return static_cast<u16>(array.stride.Value());
});
}
@@ -253,42 +251,41 @@ Maxwell::ComparisonOp FixedPipelineState::UnpackComparisonOp(u32 packed) noexcep
return static_cast<Maxwell::ComparisonOp>(packed + 1);
}
u32 FixedPipelineState::PackStencilOp(Maxwell::StencilOp::Op op) noexcept {
u32 FixedPipelineState::PackStencilOp(Maxwell::StencilOp op) noexcept {
switch (op) {
case Maxwell::StencilOp::Op::Keep_D3D:
case Maxwell::StencilOp::Op::Keep_GL:
case Maxwell::StencilOp::Keep:
case Maxwell::StencilOp::KeepOGL:
return 0;
case Maxwell::StencilOp::Op::Zero_D3D:
case Maxwell::StencilOp::Op::Zero_GL:
case Maxwell::StencilOp::Zero:
case Maxwell::StencilOp::ZeroOGL:
return 1;
case Maxwell::StencilOp::Op::Replace_D3D:
case Maxwell::StencilOp::Op::Replace_GL:
case Maxwell::StencilOp::Replace:
case Maxwell::StencilOp::ReplaceOGL:
return 2;
case Maxwell::StencilOp::Op::IncrSaturate_D3D:
case Maxwell::StencilOp::Op::IncrSaturate_GL:
case Maxwell::StencilOp::Incr:
case Maxwell::StencilOp::IncrOGL:
return 3;
case Maxwell::StencilOp::Op::DecrSaturate_D3D:
case Maxwell::StencilOp::Op::DecrSaturate_GL:
case Maxwell::StencilOp::Decr:
case Maxwell::StencilOp::DecrOGL:
return 4;
case Maxwell::StencilOp::Op::Invert_D3D:
case Maxwell::StencilOp::Op::Invert_GL:
case Maxwell::StencilOp::Invert:
case Maxwell::StencilOp::InvertOGL:
return 5;
case Maxwell::StencilOp::Op::Incr_D3D:
case Maxwell::StencilOp::Op::Incr_GL:
case Maxwell::StencilOp::IncrWrap:
case Maxwell::StencilOp::IncrWrapOGL:
return 6;
case Maxwell::StencilOp::Op::Decr_D3D:
case Maxwell::StencilOp::Op::Decr_GL:
case Maxwell::StencilOp::DecrWrap:
case Maxwell::StencilOp::DecrWrapOGL:
return 7;
}
return 0;
}
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};
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};
return LUT[packed];
}
@@ -321,30 +318,30 @@ Maxwell::PolygonMode FixedPipelineState::UnpackPolygonMode(u32 packed) noexcept
return static_cast<Maxwell::PolygonMode>(packed + 0x1B00);
}
u32 FixedPipelineState::PackLogicOp(Maxwell::LogicOp::Op op) noexcept {
u32 FixedPipelineState::PackLogicOp(Maxwell::LogicOperation op) noexcept {
return static_cast<u32>(op) - 0x1500;
}
Maxwell::LogicOp::Op FixedPipelineState::UnpackLogicOp(u32 packed) noexcept {
return static_cast<Maxwell::LogicOp::Op>(packed + 0x1500);
Maxwell::LogicOperation FixedPipelineState::UnpackLogicOp(u32 packed) noexcept {
return static_cast<Maxwell::LogicOperation>(packed + 0x1500);
}
u32 FixedPipelineState::PackBlendEquation(Maxwell::Blend::Equation equation) noexcept {
switch (equation) {
case Maxwell::Blend::Equation::Add_D3D:
case Maxwell::Blend::Equation::Add_GL:
case Maxwell::Blend::Equation::Add:
case Maxwell::Blend::Equation::AddGL:
return 0;
case Maxwell::Blend::Equation::Subtract_D3D:
case Maxwell::Blend::Equation::Subtract_GL:
case Maxwell::Blend::Equation::Subtract:
case Maxwell::Blend::Equation::SubtractGL:
return 1;
case Maxwell::Blend::Equation::ReverseSubtract_D3D:
case Maxwell::Blend::Equation::ReverseSubtract_GL:
case Maxwell::Blend::Equation::ReverseSubtract:
case Maxwell::Blend::Equation::ReverseSubtractGL:
return 2;
case Maxwell::Blend::Equation::Min_D3D:
case Maxwell::Blend::Equation::Min_GL:
case Maxwell::Blend::Equation::Min:
case Maxwell::Blend::Equation::MinGL:
return 3;
case Maxwell::Blend::Equation::Max_D3D:
case Maxwell::Blend::Equation::Max_GL:
case Maxwell::Blend::Equation::Max:
case Maxwell::Blend::Equation::MaxGL:
return 4;
}
return 0;
@@ -352,99 +349,97 @@ 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_D3D, Maxwell::Blend::Equation::Subtract_D3D,
Maxwell::Blend::Equation::ReverseSubtract_D3D, Maxwell::Blend::Equation::Min_D3D,
Maxwell::Blend::Equation::Max_D3D};
Maxwell::Blend::Equation::Add, Maxwell::Blend::Equation::Subtract,
Maxwell::Blend::Equation::ReverseSubtract, Maxwell::Blend::Equation::Min,
Maxwell::Blend::Equation::Max};
return LUT[packed];
}
u32 FixedPipelineState::PackBlendFactor(Maxwell::Blend::Factor factor) noexcept {
switch (factor) {
case Maxwell::Blend::Factor::Zero_D3D:
case Maxwell::Blend::Factor::Zero_GL:
case Maxwell::Blend::Factor::Zero:
case Maxwell::Blend::Factor::ZeroGL:
return 0;
case Maxwell::Blend::Factor::One_D3D:
case Maxwell::Blend::Factor::One_GL:
case Maxwell::Blend::Factor::One:
case Maxwell::Blend::Factor::OneGL:
return 1;
case Maxwell::Blend::Factor::SourceColor_D3D:
case Maxwell::Blend::Factor::SourceColor_GL:
case Maxwell::Blend::Factor::SourceColor:
case Maxwell::Blend::Factor::SourceColorGL:
return 2;
case Maxwell::Blend::Factor::OneMinusSourceColor_D3D:
case Maxwell::Blend::Factor::OneMinusSourceColor_GL:
case Maxwell::Blend::Factor::OneMinusSourceColor:
case Maxwell::Blend::Factor::OneMinusSourceColorGL:
return 3;
case Maxwell::Blend::Factor::SourceAlpha_D3D:
case Maxwell::Blend::Factor::SourceAlpha_GL:
case Maxwell::Blend::Factor::SourceAlpha:
case Maxwell::Blend::Factor::SourceAlphaGL:
return 4;
case Maxwell::Blend::Factor::OneMinusSourceAlpha_D3D:
case Maxwell::Blend::Factor::OneMinusSourceAlpha_GL:
case Maxwell::Blend::Factor::OneMinusSourceAlpha:
case Maxwell::Blend::Factor::OneMinusSourceAlphaGL:
return 5;
case Maxwell::Blend::Factor::DestAlpha_D3D:
case Maxwell::Blend::Factor::DestAlpha_GL:
case Maxwell::Blend::Factor::DestAlpha:
case Maxwell::Blend::Factor::DestAlphaGL:
return 6;
case Maxwell::Blend::Factor::OneMinusDestAlpha_D3D:
case Maxwell::Blend::Factor::OneMinusDestAlpha_GL:
case Maxwell::Blend::Factor::OneMinusDestAlpha:
case Maxwell::Blend::Factor::OneMinusDestAlphaGL:
return 7;
case Maxwell::Blend::Factor::DestColor_D3D:
case Maxwell::Blend::Factor::DestColor_GL:
case Maxwell::Blend::Factor::DestColor:
case Maxwell::Blend::Factor::DestColorGL:
return 8;
case Maxwell::Blend::Factor::OneMinusDestColor_D3D:
case Maxwell::Blend::Factor::OneMinusDestColor_GL:
case Maxwell::Blend::Factor::OneMinusDestColor:
case Maxwell::Blend::Factor::OneMinusDestColorGL:
return 9;
case Maxwell::Blend::Factor::SourceAlphaSaturate_D3D:
case Maxwell::Blend::Factor::SourceAlphaSaturate_GL:
case Maxwell::Blend::Factor::SourceAlphaSaturate:
case Maxwell::Blend::Factor::SourceAlphaSaturateGL:
return 10;
case Maxwell::Blend::Factor::Source1Color_D3D:
case Maxwell::Blend::Factor::Source1Color_GL:
case Maxwell::Blend::Factor::Source1Color:
case Maxwell::Blend::Factor::Source1ColorGL:
return 11;
case Maxwell::Blend::Factor::OneMinusSource1Color_D3D:
case Maxwell::Blend::Factor::OneMinusSource1Color_GL:
case Maxwell::Blend::Factor::OneMinusSource1Color:
case Maxwell::Blend::Factor::OneMinusSource1ColorGL:
return 12;
case Maxwell::Blend::Factor::Source1Alpha_D3D:
case Maxwell::Blend::Factor::Source1Alpha_GL:
case Maxwell::Blend::Factor::Source1Alpha:
case Maxwell::Blend::Factor::Source1AlphaGL:
return 13;
case Maxwell::Blend::Factor::OneMinusSource1Alpha_D3D:
case Maxwell::Blend::Factor::OneMinusSource1Alpha_GL:
case Maxwell::Blend::Factor::OneMinusSource1Alpha:
case Maxwell::Blend::Factor::OneMinusSource1AlphaGL:
return 14;
case Maxwell::Blend::Factor::BlendFactor_D3D:
case Maxwell::Blend::Factor::ConstantColor_GL:
case Maxwell::Blend::Factor::ConstantColor:
case Maxwell::Blend::Factor::ConstantColorGL:
return 15;
case Maxwell::Blend::Factor::OneMinusBlendFactor_D3D:
case Maxwell::Blend::Factor::OneMinusConstantColor_GL:
case Maxwell::Blend::Factor::OneMinusConstantColor:
case Maxwell::Blend::Factor::OneMinusConstantColorGL:
return 16;
case Maxwell::Blend::Factor::BothSourceAlpha_D3D:
case Maxwell::Blend::Factor::ConstantAlpha_GL:
case Maxwell::Blend::Factor::ConstantAlpha:
case Maxwell::Blend::Factor::ConstantAlphaGL:
return 17;
case Maxwell::Blend::Factor::OneMinusBothSourceAlpha_D3D:
case Maxwell::Blend::Factor::OneMinusConstantAlpha_GL:
case Maxwell::Blend::Factor::OneMinusConstantAlpha:
case Maxwell::Blend::Factor::OneMinusConstantAlphaGL:
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_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,
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,
};
ASSERT(packed < LUT.size());
return LUT[packed];
}

View File

@@ -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 op) noexcept;
static Maxwell::StencilOp::Op UnpackStencilOp(u32 packed) noexcept;
static u32 PackStencilOp(Maxwell::StencilOp op) noexcept;
static Maxwell::StencilOp 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::LogicOp::Op op) noexcept;
static Maxwell::LogicOp::Op UnpackLogicOp(u32 packed) noexcept;
static u32 PackLogicOp(Maxwell::LogicOperation op) noexcept;
static Maxwell::LogicOperation 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::Op ActionStencilFail() const noexcept {
Maxwell::StencilOp ActionStencilFail() const noexcept {
return UnpackStencilOp(action_stencil_fail);
}
Maxwell::StencilOp::Op ActionDepthFail() const noexcept {
Maxwell::StencilOp ActionDepthFail() const noexcept {
return UnpackStencilOp(action_depth_fail);
}
Maxwell::StencilOp::Op ActionDepthPass() const noexcept {
Maxwell::StencilOp ActionDepthPass() const noexcept {
return UnpackStencilOp(action_depth_pass);
}
@@ -193,6 +193,7 @@ 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;

View File

@@ -323,182 +323,161 @@ VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type,
Maxwell::VertexAttribute::Size size) {
const VkFormat format{([&]() {
switch (type) {
case Maxwell::VertexAttribute::Type::UnusedEnumDoNotUseBecauseItWillGoAway:
ASSERT_MSG(false, "Invalid vertex attribute type!");
break;
case Maxwell::VertexAttribute::Type::UNorm:
case Maxwell::VertexAttribute::Type::UnsignedNorm:
switch (size) {
case Maxwell::VertexAttribute::Size::Size_R8:
case Maxwell::VertexAttribute::Size::Size_A8:
case Maxwell::VertexAttribute::Size::Size_8:
return VK_FORMAT_R8_UNORM;
case Maxwell::VertexAttribute::Size::Size_R8_G8:
case Maxwell::VertexAttribute::Size::Size_G8_R8:
case Maxwell::VertexAttribute::Size::Size_8_8:
return VK_FORMAT_R8G8_UNORM;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
case Maxwell::VertexAttribute::Size::Size_8_8_8:
return VK_FORMAT_R8G8B8_UNORM;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
return VK_FORMAT_R8G8B8A8_UNORM;
case Maxwell::VertexAttribute::Size::Size_R16:
case Maxwell::VertexAttribute::Size::Size_16:
return VK_FORMAT_R16_UNORM;
case Maxwell::VertexAttribute::Size::Size_R16_G16:
case Maxwell::VertexAttribute::Size::Size_16_16:
return VK_FORMAT_R16G16_UNORM;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
case Maxwell::VertexAttribute::Size::Size_16_16_16:
return VK_FORMAT_R16G16B16_UNORM;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
return VK_FORMAT_R16G16B16A16_UNORM;
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
default:
break;
}
break;
case Maxwell::VertexAttribute::Type::SNorm:
case Maxwell::VertexAttribute::Type::SignedNorm:
switch (size) {
case Maxwell::VertexAttribute::Size::Size_R8:
case Maxwell::VertexAttribute::Size::Size_A8:
case Maxwell::VertexAttribute::Size::Size_8:
return VK_FORMAT_R8_SNORM;
case Maxwell::VertexAttribute::Size::Size_R8_G8:
case Maxwell::VertexAttribute::Size::Size_G8_R8:
case Maxwell::VertexAttribute::Size::Size_8_8:
return VK_FORMAT_R8G8_SNORM;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
case Maxwell::VertexAttribute::Size::Size_8_8_8:
return VK_FORMAT_R8G8B8_SNORM;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
return VK_FORMAT_R8G8B8A8_SNORM;
case Maxwell::VertexAttribute::Size::Size_R16:
case Maxwell::VertexAttribute::Size::Size_16:
return VK_FORMAT_R16_SNORM;
case Maxwell::VertexAttribute::Size::Size_R16_G16:
case Maxwell::VertexAttribute::Size::Size_16_16:
return VK_FORMAT_R16G16_SNORM;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
case Maxwell::VertexAttribute::Size::Size_16_16_16:
return VK_FORMAT_R16G16B16_SNORM;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
return VK_FORMAT_R16G16B16A16_SNORM;
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
return VK_FORMAT_A2B10G10R10_SNORM_PACK32;
default:
break;
}
break;
case Maxwell::VertexAttribute::Type::UScaled:
case Maxwell::VertexAttribute::Type::UnsignedScaled:
switch (size) {
case Maxwell::VertexAttribute::Size::Size_R8:
case Maxwell::VertexAttribute::Size::Size_A8:
case Maxwell::VertexAttribute::Size::Size_8:
return VK_FORMAT_R8_USCALED;
case Maxwell::VertexAttribute::Size::Size_R8_G8:
case Maxwell::VertexAttribute::Size::Size_G8_R8:
case Maxwell::VertexAttribute::Size::Size_8_8:
return VK_FORMAT_R8G8_USCALED;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
case Maxwell::VertexAttribute::Size::Size_8_8_8:
return VK_FORMAT_R8G8B8_USCALED;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
return VK_FORMAT_R8G8B8A8_USCALED;
case Maxwell::VertexAttribute::Size::Size_R16:
case Maxwell::VertexAttribute::Size::Size_16:
return VK_FORMAT_R16_USCALED;
case Maxwell::VertexAttribute::Size::Size_R16_G16:
case Maxwell::VertexAttribute::Size::Size_16_16:
return VK_FORMAT_R16G16_USCALED;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
case Maxwell::VertexAttribute::Size::Size_16_16_16:
return VK_FORMAT_R16G16B16_USCALED;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
return VK_FORMAT_R16G16B16A16_USCALED;
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
return VK_FORMAT_A2B10G10R10_USCALED_PACK32;
default:
break;
}
break;
case Maxwell::VertexAttribute::Type::SScaled:
case Maxwell::VertexAttribute::Type::SignedScaled:
switch (size) {
case Maxwell::VertexAttribute::Size::Size_R8:
case Maxwell::VertexAttribute::Size::Size_A8:
case Maxwell::VertexAttribute::Size::Size_8:
return VK_FORMAT_R8_SSCALED;
case Maxwell::VertexAttribute::Size::Size_R8_G8:
case Maxwell::VertexAttribute::Size::Size_G8_R8:
case Maxwell::VertexAttribute::Size::Size_8_8:
return VK_FORMAT_R8G8_SSCALED;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
case Maxwell::VertexAttribute::Size::Size_8_8_8:
return VK_FORMAT_R8G8B8_SSCALED;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
return VK_FORMAT_R8G8B8A8_SSCALED;
case Maxwell::VertexAttribute::Size::Size_R16:
case Maxwell::VertexAttribute::Size::Size_16:
return VK_FORMAT_R16_SSCALED;
case Maxwell::VertexAttribute::Size::Size_R16_G16:
case Maxwell::VertexAttribute::Size::Size_16_16:
return VK_FORMAT_R16G16_SSCALED;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
case Maxwell::VertexAttribute::Size::Size_16_16_16:
return VK_FORMAT_R16G16B16_SSCALED;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
return VK_FORMAT_R16G16B16A16_SSCALED;
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
return VK_FORMAT_A2B10G10R10_SSCALED_PACK32;
default:
break;
}
break;
case Maxwell::VertexAttribute::Type::UInt:
case Maxwell::VertexAttribute::Type::UnsignedInt:
switch (size) {
case Maxwell::VertexAttribute::Size::Size_R8:
case Maxwell::VertexAttribute::Size::Size_A8:
case Maxwell::VertexAttribute::Size::Size_8:
return VK_FORMAT_R8_UINT;
case Maxwell::VertexAttribute::Size::Size_R8_G8:
case Maxwell::VertexAttribute::Size::Size_G8_R8:
case Maxwell::VertexAttribute::Size::Size_8_8:
return VK_FORMAT_R8G8_UINT;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
case Maxwell::VertexAttribute::Size::Size_8_8_8:
return VK_FORMAT_R8G8B8_UINT;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
return VK_FORMAT_R8G8B8A8_UINT;
case Maxwell::VertexAttribute::Size::Size_R16:
case Maxwell::VertexAttribute::Size::Size_16:
return VK_FORMAT_R16_UINT;
case Maxwell::VertexAttribute::Size::Size_R16_G16:
case Maxwell::VertexAttribute::Size::Size_16_16:
return VK_FORMAT_R16G16_UINT;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
case Maxwell::VertexAttribute::Size::Size_16_16_16:
return VK_FORMAT_R16G16B16_UINT;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
return VK_FORMAT_R16G16B16A16_UINT;
case Maxwell::VertexAttribute::Size::Size_R32:
case Maxwell::VertexAttribute::Size::Size_32:
return VK_FORMAT_R32_UINT;
case Maxwell::VertexAttribute::Size::Size_R32_G32:
case Maxwell::VertexAttribute::Size::Size_32_32:
return VK_FORMAT_R32G32_UINT;
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
case Maxwell::VertexAttribute::Size::Size_32_32_32:
return VK_FORMAT_R32G32B32_UINT;
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
return VK_FORMAT_R32G32B32A32_UINT;
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
return VK_FORMAT_A2B10G10R10_UINT_PACK32;
default:
break;
}
break;
case Maxwell::VertexAttribute::Type::SInt:
case Maxwell::VertexAttribute::Type::SignedInt:
switch (size) {
case Maxwell::VertexAttribute::Size::Size_R8:
case Maxwell::VertexAttribute::Size::Size_A8:
case Maxwell::VertexAttribute::Size::Size_8:
return VK_FORMAT_R8_SINT;
case Maxwell::VertexAttribute::Size::Size_R8_G8:
case Maxwell::VertexAttribute::Size::Size_G8_R8:
case Maxwell::VertexAttribute::Size::Size_8_8:
return VK_FORMAT_R8G8_SINT;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
case Maxwell::VertexAttribute::Size::Size_8_8_8:
return VK_FORMAT_R8G8B8_SINT;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
return VK_FORMAT_R8G8B8A8_SINT;
case Maxwell::VertexAttribute::Size::Size_R16:
case Maxwell::VertexAttribute::Size::Size_16:
return VK_FORMAT_R16_SINT;
case Maxwell::VertexAttribute::Size::Size_R16_G16:
case Maxwell::VertexAttribute::Size::Size_16_16:
return VK_FORMAT_R16G16_SINT;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
case Maxwell::VertexAttribute::Size::Size_16_16_16:
return VK_FORMAT_R16G16B16_SINT;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
return VK_FORMAT_R16G16B16A16_SINT;
case Maxwell::VertexAttribute::Size::Size_R32:
case Maxwell::VertexAttribute::Size::Size_32:
return VK_FORMAT_R32_SINT;
case Maxwell::VertexAttribute::Size::Size_R32_G32:
case Maxwell::VertexAttribute::Size::Size_32_32:
return VK_FORMAT_R32G32_SINT;
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
case Maxwell::VertexAttribute::Size::Size_32_32_32:
return VK_FORMAT_R32G32B32_SINT;
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
return VK_FORMAT_R32G32B32A32_SINT;
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
return VK_FORMAT_A2B10G10R10_SINT_PACK32;
default:
break;
@@ -506,23 +485,23 @@ VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type,
break;
case Maxwell::VertexAttribute::Type::Float:
switch (size) {
case Maxwell::VertexAttribute::Size::Size_R16:
case Maxwell::VertexAttribute::Size::Size_16:
return VK_FORMAT_R16_SFLOAT;
case Maxwell::VertexAttribute::Size::Size_R16_G16:
case Maxwell::VertexAttribute::Size::Size_16_16:
return VK_FORMAT_R16G16_SFLOAT;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
case Maxwell::VertexAttribute::Size::Size_16_16_16:
return VK_FORMAT_R16G16B16_SFLOAT;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
return VK_FORMAT_R16G16B16A16_SFLOAT;
case Maxwell::VertexAttribute::Size::Size_R32:
case Maxwell::VertexAttribute::Size::Size_32:
return VK_FORMAT_R32_SFLOAT;
case Maxwell::VertexAttribute::Size::Size_R32_G32:
case Maxwell::VertexAttribute::Size::Size_32_32:
return VK_FORMAT_R32G32_SFLOAT;
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
case Maxwell::VertexAttribute::Size::Size_32_32_32:
return VK_FORMAT_R32G32B32_SFLOAT;
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
return VK_FORMAT_R32G32B32A32_SFLOAT;
case Maxwell::VertexAttribute::Size::Size_B10_G11_R11:
case Maxwell::VertexAttribute::Size::Size_11_11_10:
return VK_FORMAT_B10G11R11_UFLOAT_PACK32;
default:
break;
@@ -542,29 +521,29 @@ VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type,
VkCompareOp ComparisonOp(Maxwell::ComparisonOp comparison) {
switch (comparison) {
case Maxwell::ComparisonOp::Never_D3D:
case Maxwell::ComparisonOp::Never_GL:
case Maxwell::ComparisonOp::Never:
case Maxwell::ComparisonOp::NeverOld:
return VK_COMPARE_OP_NEVER;
case Maxwell::ComparisonOp::Less_D3D:
case Maxwell::ComparisonOp::Less_GL:
case Maxwell::ComparisonOp::Less:
case Maxwell::ComparisonOp::LessOld:
return VK_COMPARE_OP_LESS;
case Maxwell::ComparisonOp::Equal_D3D:
case Maxwell::ComparisonOp::Equal_GL:
case Maxwell::ComparisonOp::Equal:
case Maxwell::ComparisonOp::EqualOld:
return VK_COMPARE_OP_EQUAL;
case Maxwell::ComparisonOp::LessEqual_D3D:
case Maxwell::ComparisonOp::LessEqual_GL:
case Maxwell::ComparisonOp::LessEqual:
case Maxwell::ComparisonOp::LessEqualOld:
return VK_COMPARE_OP_LESS_OR_EQUAL;
case Maxwell::ComparisonOp::Greater_D3D:
case Maxwell::ComparisonOp::Greater_GL:
case Maxwell::ComparisonOp::Greater:
case Maxwell::ComparisonOp::GreaterOld:
return VK_COMPARE_OP_GREATER;
case Maxwell::ComparisonOp::NotEqual_D3D:
case Maxwell::ComparisonOp::NotEqual_GL:
case Maxwell::ComparisonOp::NotEqual:
case Maxwell::ComparisonOp::NotEqualOld:
return VK_COMPARE_OP_NOT_EQUAL;
case Maxwell::ComparisonOp::GreaterEqual_D3D:
case Maxwell::ComparisonOp::GreaterEqual_GL:
case Maxwell::ComparisonOp::GreaterEqual:
case Maxwell::ComparisonOp::GreaterEqualOld:
return VK_COMPARE_OP_GREATER_OR_EQUAL;
case Maxwell::ComparisonOp::Always_D3D:
case Maxwell::ComparisonOp::Always_GL:
case Maxwell::ComparisonOp::Always:
case Maxwell::ComparisonOp::AlwaysOld:
return VK_COMPARE_OP_ALWAYS;
}
UNIMPLEMENTED_MSG("Unimplemented comparison op={}", comparison);
@@ -584,31 +563,31 @@ VkIndexType IndexFormat(Maxwell::IndexFormat index_format) {
return {};
}
VkStencilOp StencilOp(Maxwell::StencilOp::Op stencil_op) {
VkStencilOp StencilOp(Maxwell::StencilOp stencil_op) {
switch (stencil_op) {
case Maxwell::StencilOp::Op::Keep_D3D:
case Maxwell::StencilOp::Op::Keep_GL:
case Maxwell::StencilOp::Keep:
case Maxwell::StencilOp::KeepOGL:
return VK_STENCIL_OP_KEEP;
case Maxwell::StencilOp::Op::Zero_D3D:
case Maxwell::StencilOp::Op::Zero_GL:
case Maxwell::StencilOp::Zero:
case Maxwell::StencilOp::ZeroOGL:
return VK_STENCIL_OP_ZERO;
case Maxwell::StencilOp::Op::Replace_D3D:
case Maxwell::StencilOp::Op::Replace_GL:
case Maxwell::StencilOp::Replace:
case Maxwell::StencilOp::ReplaceOGL:
return VK_STENCIL_OP_REPLACE;
case Maxwell::StencilOp::Op::IncrSaturate_D3D:
case Maxwell::StencilOp::Op::IncrSaturate_GL:
case Maxwell::StencilOp::Incr:
case Maxwell::StencilOp::IncrOGL:
return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
case Maxwell::StencilOp::Op::DecrSaturate_D3D:
case Maxwell::StencilOp::Op::DecrSaturate_GL:
case Maxwell::StencilOp::Decr:
case Maxwell::StencilOp::DecrOGL:
return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
case Maxwell::StencilOp::Op::Invert_D3D:
case Maxwell::StencilOp::Op::Invert_GL:
case Maxwell::StencilOp::Invert:
case Maxwell::StencilOp::InvertOGL:
return VK_STENCIL_OP_INVERT;
case Maxwell::StencilOp::Op::Incr_D3D:
case Maxwell::StencilOp::Op::Incr_GL:
case Maxwell::StencilOp::IncrWrap:
case Maxwell::StencilOp::IncrWrapOGL:
return VK_STENCIL_OP_INCREMENT_AND_WRAP;
case Maxwell::StencilOp::Op::Decr_D3D:
case Maxwell::StencilOp::Op::Decr_GL:
case Maxwell::StencilOp::DecrWrap:
case Maxwell::StencilOp::DecrWrapOGL:
return VK_STENCIL_OP_DECREMENT_AND_WRAP;
}
UNIMPLEMENTED_MSG("Unimplemented stencil op={}", stencil_op);
@@ -617,20 +596,20 @@ VkStencilOp StencilOp(Maxwell::StencilOp::Op stencil_op) {
VkBlendOp BlendEquation(Maxwell::Blend::Equation equation) {
switch (equation) {
case Maxwell::Blend::Equation::Add_D3D:
case Maxwell::Blend::Equation::Add_GL:
case Maxwell::Blend::Equation::Add:
case Maxwell::Blend::Equation::AddGL:
return VK_BLEND_OP_ADD;
case Maxwell::Blend::Equation::Subtract_D3D:
case Maxwell::Blend::Equation::Subtract_GL:
case Maxwell::Blend::Equation::Subtract:
case Maxwell::Blend::Equation::SubtractGL:
return VK_BLEND_OP_SUBTRACT;
case Maxwell::Blend::Equation::ReverseSubtract_D3D:
case Maxwell::Blend::Equation::ReverseSubtract_GL:
case Maxwell::Blend::Equation::ReverseSubtract:
case Maxwell::Blend::Equation::ReverseSubtractGL:
return VK_BLEND_OP_REVERSE_SUBTRACT;
case Maxwell::Blend::Equation::Min_D3D:
case Maxwell::Blend::Equation::Min_GL:
case Maxwell::Blend::Equation::Min:
case Maxwell::Blend::Equation::MinGL:
return VK_BLEND_OP_MIN;
case Maxwell::Blend::Equation::Max_D3D:
case Maxwell::Blend::Equation::Max_GL:
case Maxwell::Blend::Equation::Max:
case Maxwell::Blend::Equation::MaxGL:
return VK_BLEND_OP_MAX;
}
UNIMPLEMENTED_MSG("Unimplemented blend equation={}", equation);
@@ -639,62 +618,62 @@ VkBlendOp BlendEquation(Maxwell::Blend::Equation equation) {
VkBlendFactor BlendFactor(Maxwell::Blend::Factor factor) {
switch (factor) {
case Maxwell::Blend::Factor::Zero_D3D:
case Maxwell::Blend::Factor::Zero_GL:
case Maxwell::Blend::Factor::Zero:
case Maxwell::Blend::Factor::ZeroGL:
return VK_BLEND_FACTOR_ZERO;
case Maxwell::Blend::Factor::One_D3D:
case Maxwell::Blend::Factor::One_GL:
case Maxwell::Blend::Factor::One:
case Maxwell::Blend::Factor::OneGL:
return VK_BLEND_FACTOR_ONE;
case Maxwell::Blend::Factor::SourceColor_D3D:
case Maxwell::Blend::Factor::SourceColor_GL:
case Maxwell::Blend::Factor::SourceColor:
case Maxwell::Blend::Factor::SourceColorGL:
return VK_BLEND_FACTOR_SRC_COLOR;
case Maxwell::Blend::Factor::OneMinusSourceColor_D3D:
case Maxwell::Blend::Factor::OneMinusSourceColor_GL:
case Maxwell::Blend::Factor::OneMinusSourceColor:
case Maxwell::Blend::Factor::OneMinusSourceColorGL:
return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
case Maxwell::Blend::Factor::SourceAlpha_D3D:
case Maxwell::Blend::Factor::SourceAlpha_GL:
case Maxwell::Blend::Factor::SourceAlpha:
case Maxwell::Blend::Factor::SourceAlphaGL:
return VK_BLEND_FACTOR_SRC_ALPHA;
case Maxwell::Blend::Factor::OneMinusSourceAlpha_D3D:
case Maxwell::Blend::Factor::OneMinusSourceAlpha_GL:
case Maxwell::Blend::Factor::OneMinusSourceAlpha:
case Maxwell::Blend::Factor::OneMinusSourceAlphaGL:
return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
case Maxwell::Blend::Factor::DestAlpha_D3D:
case Maxwell::Blend::Factor::DestAlpha_GL:
case Maxwell::Blend::Factor::DestAlpha:
case Maxwell::Blend::Factor::DestAlphaGL:
return VK_BLEND_FACTOR_DST_ALPHA;
case Maxwell::Blend::Factor::OneMinusDestAlpha_D3D:
case Maxwell::Blend::Factor::OneMinusDestAlpha_GL:
case Maxwell::Blend::Factor::OneMinusDestAlpha:
case Maxwell::Blend::Factor::OneMinusDestAlphaGL:
return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
case Maxwell::Blend::Factor::DestColor_D3D:
case Maxwell::Blend::Factor::DestColor_GL:
case Maxwell::Blend::Factor::DestColor:
case Maxwell::Blend::Factor::DestColorGL:
return VK_BLEND_FACTOR_DST_COLOR;
case Maxwell::Blend::Factor::OneMinusDestColor_D3D:
case Maxwell::Blend::Factor::OneMinusDestColor_GL:
case Maxwell::Blend::Factor::OneMinusDestColor:
case Maxwell::Blend::Factor::OneMinusDestColorGL:
return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
case Maxwell::Blend::Factor::SourceAlphaSaturate_D3D:
case Maxwell::Blend::Factor::SourceAlphaSaturate_GL:
case Maxwell::Blend::Factor::SourceAlphaSaturate:
case Maxwell::Blend::Factor::SourceAlphaSaturateGL:
return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
case Maxwell::Blend::Factor::Source1Color_D3D:
case Maxwell::Blend::Factor::Source1Color_GL:
case Maxwell::Blend::Factor::Source1Color:
case Maxwell::Blend::Factor::Source1ColorGL:
return VK_BLEND_FACTOR_SRC1_COLOR;
case Maxwell::Blend::Factor::OneMinusSource1Color_D3D:
case Maxwell::Blend::Factor::OneMinusSource1Color_GL:
case Maxwell::Blend::Factor::OneMinusSource1Color:
case Maxwell::Blend::Factor::OneMinusSource1ColorGL:
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
case Maxwell::Blend::Factor::Source1Alpha_D3D:
case Maxwell::Blend::Factor::Source1Alpha_GL:
case Maxwell::Blend::Factor::Source1Alpha:
case Maxwell::Blend::Factor::Source1AlphaGL:
return VK_BLEND_FACTOR_SRC1_ALPHA;
case Maxwell::Blend::Factor::OneMinusSource1Alpha_D3D:
case Maxwell::Blend::Factor::OneMinusSource1Alpha_GL:
case Maxwell::Blend::Factor::OneMinusSource1Alpha:
case Maxwell::Blend::Factor::OneMinusSource1AlphaGL:
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
case Maxwell::Blend::Factor::BlendFactor_D3D:
case Maxwell::Blend::Factor::ConstantColor_GL:
case Maxwell::Blend::Factor::ConstantColor:
case Maxwell::Blend::Factor::ConstantColorGL:
return VK_BLEND_FACTOR_CONSTANT_COLOR;
case Maxwell::Blend::Factor::OneMinusBlendFactor_D3D:
case Maxwell::Blend::Factor::OneMinusConstantColor_GL:
case Maxwell::Blend::Factor::OneMinusConstantColor:
case Maxwell::Blend::Factor::OneMinusConstantColorGL:
return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
case Maxwell::Blend::Factor::BothSourceAlpha_D3D:
case Maxwell::Blend::Factor::ConstantAlpha_GL:
case Maxwell::Blend::Factor::ConstantAlpha:
case Maxwell::Blend::Factor::ConstantAlphaGL:
return VK_BLEND_FACTOR_CONSTANT_ALPHA;
case Maxwell::Blend::Factor::OneMinusBothSourceAlpha_D3D:
case Maxwell::Blend::Factor::OneMinusConstantAlpha_GL:
case Maxwell::Blend::Factor::OneMinusConstantAlpha:
case Maxwell::Blend::Factor::OneMinusConstantAlphaGL:
return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
}
UNIMPLEMENTED_MSG("Unimplemented blend factor={}", factor);

View File

@@ -55,7 +55,7 @@ VkCompareOp ComparisonOp(Maxwell::ComparisonOp comparison);
VkIndexType IndexFormat(Maxwell::IndexFormat index_format);
VkStencilOp StencilOp(Maxwell::StencilOp::Op stencil_op);
VkStencilOp StencilOp(Maxwell::StencilOp stencil_op);
VkBlendOp BlendEquation(Maxwell::Blend::Equation equation);

View File

@@ -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_binding == Maxwell::SamplerBinding::ViaHeaderBinding};
const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex};
const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
const Shader::Info& info{stage_infos[stage]};
buffer_cache.UnbindGraphicsStorageBuffers(stage);
@@ -664,6 +664,15 @@ 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,
@@ -674,6 +683,9 @@ 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);
}

View File

@@ -62,29 +62,29 @@ auto MakeSpan(Container& container) {
Shader::CompareFunction MaxwellToCompareFunction(Maxwell::ComparisonOp comparison) {
switch (comparison) {
case Maxwell::ComparisonOp::Never_D3D:
case Maxwell::ComparisonOp::Never_GL:
case Maxwell::ComparisonOp::Never:
case Maxwell::ComparisonOp::NeverOld:
return Shader::CompareFunction::Never;
case Maxwell::ComparisonOp::Less_D3D:
case Maxwell::ComparisonOp::Less_GL:
case Maxwell::ComparisonOp::Less:
case Maxwell::ComparisonOp::LessOld:
return Shader::CompareFunction::Less;
case Maxwell::ComparisonOp::Equal_D3D:
case Maxwell::ComparisonOp::Equal_GL:
case Maxwell::ComparisonOp::Equal:
case Maxwell::ComparisonOp::EqualOld:
return Shader::CompareFunction::Equal;
case Maxwell::ComparisonOp::LessEqual_D3D:
case Maxwell::ComparisonOp::LessEqual_GL:
case Maxwell::ComparisonOp::LessEqual:
case Maxwell::ComparisonOp::LessEqualOld:
return Shader::CompareFunction::LessThanEqual;
case Maxwell::ComparisonOp::Greater_D3D:
case Maxwell::ComparisonOp::Greater_GL:
case Maxwell::ComparisonOp::Greater:
case Maxwell::ComparisonOp::GreaterOld:
return Shader::CompareFunction::Greater;
case Maxwell::ComparisonOp::NotEqual_D3D:
case Maxwell::ComparisonOp::NotEqual_GL:
case Maxwell::ComparisonOp::NotEqual:
case Maxwell::ComparisonOp::NotEqualOld:
return Shader::CompareFunction::NotEqual;
case Maxwell::ComparisonOp::GreaterEqual_D3D:
case Maxwell::ComparisonOp::GreaterEqual_GL:
case Maxwell::ComparisonOp::GreaterEqual:
case Maxwell::ComparisonOp::GreaterEqualOld:
return Shader::CompareFunction::GreaterThanEqual;
case Maxwell::ComparisonOp::Always_D3D:
case Maxwell::ComparisonOp::Always_GL:
case Maxwell::ComparisonOp::Always:
case Maxwell::ComparisonOp::AlwaysOld:
return Shader::CompareFunction::Always;
}
UNIMPLEMENTED_MSG("Unimplemented comparison op={}", comparison);
@@ -96,18 +96,15 @@ Shader::AttributeType CastAttributeType(const FixedPipelineState::VertexAttribut
return Shader::AttributeType::Disabled;
}
switch (attr.Type()) {
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::SignedNorm:
case Maxwell::VertexAttribute::Type::UnsignedNorm:
case Maxwell::VertexAttribute::Type::UnsignedScaled:
case Maxwell::VertexAttribute::Type::SignedScaled:
case Maxwell::VertexAttribute::Type::Float:
return Shader::AttributeType::Float;
case Maxwell::VertexAttribute::Type::SInt:
case Maxwell::VertexAttribute::Type::SignedInt:
return Shader::AttributeType::SignedInt;
case Maxwell::VertexAttribute::Type::UInt:
case Maxwell::VertexAttribute::Type::UnsignedInt:
return Shader::AttributeType::UnsignedInt;
}
return Shader::AttributeType::Float;
@@ -165,14 +162,16 @@ 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::Tessellation::DomainType>(raw)) {
case Maxwell::Tessellation::DomainType::Isolines:
switch (static_cast<Maxwell::TessellationPrimitive>(raw)) {
case Maxwell::TessellationPrimitive::Isolines:
return Shader::TessPrimitive::Isolines;
case Maxwell::Tessellation::DomainType::Triangles:
case Maxwell::TessellationPrimitive::Triangles:
return Shader::TessPrimitive::Triangles;
case Maxwell::Tessellation::DomainType::Quads:
case Maxwell::TessellationPrimitive::Quads:
return Shader::TessPrimitive::Quads;
}
ASSERT(false);
@@ -180,12 +179,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::Tessellation::Spacing>(raw)) {
case Maxwell::Tessellation::Spacing::Integer:
switch (static_cast<Maxwell::TessellationSpacing>(raw)) {
case Maxwell::TessellationSpacing::Equal:
return Shader::TessSpacing::Equal;
case Maxwell::Tessellation::Spacing::FractionalOdd:
case Maxwell::TessellationSpacing::FractionalOdd:
return Shader::TessSpacing::FractionalOdd;
case Maxwell::Tessellation::Spacing::FractionalEven:
case Maxwell::TessellationSpacing::FractionalEven:
return Shader::TessSpacing::FractionalEven;
}
ASSERT(false);
@@ -491,7 +490,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_buffer.count <= 6 || maxwell3d->regs.vertex_buffer.count <= 6) {
if (maxwell3d->regs.index_array.count <= 6 || maxwell3d->regs.vertex_buffer.count <= 6) {
return pipeline;
}
return nullptr;

View File

@@ -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.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft;
bool y_negate = regs.screen_y_control.y_negate;
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.global_base_instance_index,
.base_instance = regs.vb_base_instance,
.num_instances = is_instanced ? num_instances : 1,
.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,
.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,
.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_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;
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;
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_control.use_scissor ? GetScissorState(regs, 0, up_scale, down_shift)
: default_scissor,
.baseArrayLayer = regs.clear_surface.layer,
.rect = regs.clear_flags.scissor ? GetScissorState(regs, 0, up_scale, down_shift)
: default_scissor,
.baseArrayLayer = regs.clear_buffers.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_surface.RT;
const u32 color_attachment = regs.clear_buffers.RT;
if (use_color && framebuffer->HasAspectColorBit(color_attachment)) {
VkClearValue clear_value;
bool is_integer = false;
@@ -289,8 +289,7 @@ void RasterizerVulkan::Clear() {
break;
}
if (!is_integer) {
std::memcpy(clear_value.color.float32, regs.clear_color.data(),
regs.clear_color.size() * sizeof(f32));
std::memcpy(clear_value.color.float32, regs.clear_color, sizeof(regs.clear_color));
} else if (!is_signed) {
for (size_t i = 0; i < 4; i++) {
clear_value.color.uint32[i] = static_cast<u32>(
@@ -649,23 +648,23 @@ void RasterizerVulkan::UpdateDynamicStates() {
void RasterizerVulkan::BeginTransformFeedback() {
const auto& regs = maxwell3d->regs;
if (regs.transform_feedback_enabled == 0) {
if (regs.tfb_enabled == 0) {
return;
}
if (!device.IsExtTransformFeedbackSupported()) {
LOG_ERROR(Render_Vulkan, "Transform feedbacks used but not supported");
return;
}
UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderType::TessellationInit) ||
regs.IsShaderConfigEnabled(Maxwell::ShaderType::Tessellation) ||
regs.IsShaderConfigEnabled(Maxwell::ShaderType::Geometry));
UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationControl) ||
regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationEval) ||
regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::Geometry));
scheduler.Record(
[](vk::CommandBuffer cmdbuf) { cmdbuf.BeginTransformFeedbackEXT(0, 0, nullptr, nullptr); });
}
void RasterizerVulkan::EndTransformFeedback() {
const auto& regs = maxwell3d->regs;
if (regs.transform_feedback_enabled == 0) {
if (regs.tfb_enabled == 0) {
return;
}
if (!device.IsExtTransformFeedbackSupported()) {
@@ -729,11 +728,11 @@ void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchDepthBias()) {
return;
}
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;
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;
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
@@ -741,8 +740,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.depth_bias_clamp,
factor = regs.slope_scale_depth_bias](vk::CommandBuffer cmdbuf) {
scheduler.Record([constant = units, clamp = regs.polygon_offset_clamp,
factor = regs.polygon_offset_factor](vk::CommandBuffer cmdbuf) {
cmdbuf.SetDepthBias(constant, clamp, factor);
});
}
@@ -772,11 +771,10 @@ 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_func.mask,
front_test_mask = regs.stencil_front_func.func_mask,
back_ref = regs.stencil_back_func.ref, back_write_mask = regs.stencil_back_func.mask,
back_test_mask = regs.stencil_back_func.func_mask](vk::CommandBuffer cmdbuf) {
[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,
back_write_mask = regs.stencil_back_mask,
back_test_mask = regs.stencil_back_func_mask](vk::CommandBuffer cmdbuf) {
// Front face
cmdbuf.SetStencilReference(VK_STENCIL_FACE_FRONT_BIT, front_ref);
cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_FRONT_BIT, front_write_mask);
@@ -789,9 +787,8 @@ 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_func.mask,
test_mask = regs.stencil_front_func.func_mask](vk::CommandBuffer cmdbuf) {
scheduler.Record([ref = regs.stencil_front_func_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);
cmdbuf.SetStencilCompareMask(VK_STENCIL_FACE_FRONT_AND_BACK, test_mask);
@@ -803,8 +800,7 @@ void RasterizerVulkan::UpdateLineWidth(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchLineWidth()) {
return;
}
const float width =
regs.line_anti_alias_enable ? regs.line_width_smooth : regs.line_width_aliased;
const float width = regs.line_smooth_enable ? regs.line_width_smooth : regs.line_width_aliased;
scheduler.Record([width](vk::CommandBuffer cmdbuf) { cmdbuf.SetLineWidth(width); });
}
@@ -812,10 +808,10 @@ void RasterizerVulkan::UpdateCullMode(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchCullMode()) {
return;
}
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);
});
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);
});
}
void RasterizerVulkan::UpdateDepthBoundsTestEnable(Tegra::Engines::Maxwell3D::Regs& regs) {
@@ -864,8 +860,8 @@ void RasterizerVulkan::UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs) {
return;
}
VkFrontFace front_face = MaxwellToVK::FrontFace(regs.gl_front_face);
if (regs.window_origin.flip_y != 0) {
VkFrontFace front_face = MaxwellToVK::FrontFace(regs.front_face);
if (regs.screen_y_control.triangle_rast_flip != 0) {
front_face = front_face == VK_FRONT_FACE_CLOCKWISE ? VK_FRONT_FACE_COUNTER_CLOCKWISE
: VK_FRONT_FACE_CLOCKWISE;
}
@@ -877,16 +873,16 @@ void RasterizerVulkan::UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchStencilOp()) {
return;
}
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;
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;
if (regs.stencil_two_side_enable) {
// Separate stencil op per face
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;
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;
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),
@@ -958,15 +954,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_streams[binding]};
const bool is_instanced{regs.vertex_stream_instances.IsInstancingEnabled(binding)};
const auto& input_binding{regs.vertex_array[binding]};
const bool is_instanced{regs.instanced_arrays.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.frequency : 1,
.divisor = is_instanced ? input_binding.divisor : 1,
});
}
scheduler.Record([bindings, attributes](vk::CommandBuffer cmdbuf) {

View File

@@ -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();
}

View File

@@ -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_scale_offset_enbled)] = Viewports;
tables[1][OFF(window_origin)] = Viewports;
tables[0][OFF(viewport_transform_enabled)] = Viewports;
tables[1][OFF(screen_y_control)] = Viewports;
}
void SetupDirtyScissors(Tables& tables) {
@@ -61,9 +61,9 @@ void SetupDirtyScissors(Tables& tables) {
void SetupDirtyDepthBias(Tables& tables) {
auto& table = tables[0];
table[OFF(depth_bias)] = DepthBias;
table[OFF(depth_bias_clamp)] = DepthBias;
table[OFF(slope_scale_depth_bias)] = DepthBias;
table[OFF(polygon_offset_units)] = DepthBias;
table[OFF(polygon_offset_clamp)] = DepthBias;
table[OFF(polygon_offset_factor)] = DepthBias;
}
void SetupDirtyBlendConstants(Tables& tables) {
@@ -77,12 +77,12 @@ 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_func.mask)] = StencilProperties;
table[OFF(stencil_front_func.func_mask)] = StencilProperties;
table[OFF(stencil_back_func.ref)] = StencilProperties;
table[OFF(stencil_back_func.mask)] = StencilProperties;
table[OFF(stencil_back_func.func_mask)] = 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;
}
void SetupDirtyLineWidth(Tables& tables) {
@@ -92,8 +92,8 @@ void SetupDirtyLineWidth(Tables& tables) {
void SetupDirtyCullMode(Tables& tables) {
auto& table = tables[0];
table[OFF(gl_cull_face)] = CullMode;
table[OFF(gl_cull_test_enabled)] = CullMode;
table[OFF(cull_face)] = CullMode;
table[OFF(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(gl_front_face)] = FrontFace;
table[OFF(window_origin)] = FrontFace;
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_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[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;
@@ -139,10 +139,10 @@ void SetupDirtyStencilTestEnable(Tables& tables) {
void SetupDirtyBlending(Tables& tables) {
tables[0][OFF(color_mask_common)] = Blending;
tables[0][OFF(blend_per_target_enabled)] = 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(blend_per_target), NUM(blend_per_target), Blending);
FillBlock(tables[0], OFF(independent_blend), NUM(independent_blend), 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(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;
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;
}
}
} // Anonymous namespace

View File

@@ -43,14 +43,14 @@ bool ShaderCache::RefreshStages(std::array<u64, 6>& unique_hashes) {
}
dirty[VideoCommon::Dirty::Shaders] = false;
const GPUVAddr base_addr{maxwell3d->regs.program_region.Address()};
const GPUVAddr base_addr{maxwell3d->regs.code_address.CodeAddress()};
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.pipelines[index]};
const auto program{static_cast<Tegra::Engines::Maxwell3D::Regs::ShaderType>(index)};
const auto& shader_config{maxwell3d->regs.shader_config[index]};
const auto program{static_cast<Tegra::Engines::Maxwell3D::Regs::ShaderProgram>(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.program_region.Address()};
const GPUVAddr base_addr{maxwell3d->regs.code_address.CodeAddress()};
for (size_t index = 0; index < NUM_PROGRAMS; ++index) {
if (unique_hashes[index] == 0) {
continue;
}
const auto program{static_cast<Tegra::Engines::Maxwell3D::Regs::ShaderType>(index)};
const auto program{static_cast<Tegra::Engines::Maxwell3D::Regs::ShaderProgram>(index)};
auto& env{result.envs[index]};
const u32 start_address{maxwell3d->regs.pipelines[index].offset};
const u32 start_address{maxwell3d->regs.shader_config[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;

View File

@@ -250,34 +250,34 @@ Shader::TextureType GenericEnvironment::ReadTextureTypeImpl(GPUVAddr tic_addr, u
GraphicsEnvironment::GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_,
Tegra::MemoryManager& gpu_memory_,
Maxwell::ShaderType program, GPUVAddr program_base_,
Maxwell::ShaderProgram 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.post_vtg_shader_attrib_skip_mask;
gp_passthrough_mask = maxwell3d->regs.gp_passthrough_mask;
switch (program) {
case Maxwell::ShaderType::VertexA:
case Maxwell::ShaderProgram::VertexA:
stage = Shader::Stage::VertexA;
stage_index = 0;
break;
case Maxwell::ShaderType::VertexB:
case Maxwell::ShaderProgram::VertexB:
stage = Shader::Stage::VertexB;
stage_index = 0;
break;
case Maxwell::ShaderType::TessellationInit:
case Maxwell::ShaderProgram::TesselationControl:
stage = Shader::Stage::TessellationControl;
stage_index = 1;
break;
case Maxwell::ShaderType::Tessellation:
case Maxwell::ShaderProgram::TesselationEval:
stage = Shader::Stage::TessellationEval;
stage_index = 2;
break;
case Maxwell::ShaderType::Geometry:
case Maxwell::ShaderProgram::Geometry:
stage = Shader::Stage::Geometry;
stage_index = 3;
break;
case Maxwell::ShaderType::Pixel:
case Maxwell::ShaderProgram::Fragment:
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.bindless_texture_const_buffer_slot;
texture_bound = maxwell3d->regs.tex_cb_index;
}
u32 GraphicsEnvironment::ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) {
@@ -304,9 +304,8 @@ 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_binding == Maxwell::SamplerBinding::ViaHeaderBinding};
return ReadTextureTypeImpl(regs.tex_header.Address(), regs.tex_header.limit, via_header_index,
handle);
const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex};
return ReadTextureTypeImpl(regs.tic.Address(), regs.tic.limit, via_header_index, handle);
}
ComputeEnvironment::ComputeEnvironment(Tegra::Engines::KeplerCompute& kepler_compute_,

View File

@@ -93,7 +93,7 @@ public:
explicit GraphicsEnvironment() = default;
explicit GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_,
Tegra::MemoryManager& gpu_memory_,
Tegra::Engines::Maxwell3D::Regs::ShaderType program,
Tegra::Engines::Maxwell3D::Regs::ShaderProgram program,
GPUVAddr program_base_, u32 start_address_);
~GraphicsEnvironment() override = default;

View File

@@ -73,17 +73,17 @@ bool SurfaceTargetIsArray(SurfaceTarget target) {
PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) {
switch (format) {
case Tegra::DepthFormat::Z24_UNORM_S8_UINT:
case Tegra::DepthFormat::S8_UINT_Z24_UNORM:
return PixelFormat::S8_UINT_D24_UNORM;
case Tegra::DepthFormat::S8Z24_UNORM:
case Tegra::DepthFormat::D24S8_UNORM:
return PixelFormat::D24_UNORM_S8_UINT;
case Tegra::DepthFormat::Z32_FLOAT:
case Tegra::DepthFormat::D32_FLOAT:
return PixelFormat::D32_FLOAT;
case Tegra::DepthFormat::Z16_UNORM:
case Tegra::DepthFormat::D16_UNORM:
return PixelFormat::D16_UNORM;
case Tegra::DepthFormat::S8_UINT:
return PixelFormat::S8_UINT;
case Tegra::DepthFormat::Z32_FLOAT_X24S8_UINT:
case Tegra::DepthFormat::D32_FLOAT_S8X24_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::A8R8G8B8_UNORM:
case Tegra::RenderTargetFormat::B8G8R8A8_UNORM:
return PixelFormat::B8G8R8A8_UNORM;
case Tegra::RenderTargetFormat::A8R8G8B8_SRGB:
case Tegra::RenderTargetFormat::B8G8R8A8_SRGB:
return PixelFormat::B8G8R8A8_SRGB;
case Tegra::RenderTargetFormat::A2B10G10R10_UNORM:
return PixelFormat::A2B10G10R10_UNORM;

View File

@@ -1,8 +1,6 @@
// 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"
@@ -14,7 +12,6 @@
namespace VideoCommon {
using Tegra::Engines::Maxwell3D;
using Tegra::Texture::TextureType;
using Tegra::Texture::TICEntry;
using VideoCore::Surface::PixelFormat;
@@ -110,13 +107,12 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept {
}
}
ImageInfo::ImageInfo(const Maxwell3D::Regs& regs, size_t index) noexcept {
ImageInfo::ImageInfo(const Tegra::Engines::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.dim_control ==
Maxwell3D::Regs::TileMode::DimensionControl::DepthDefinesArray);
ASSERT(rt.tile_mode.is_3d == 0);
type = ImageType::Linear;
pitch = rt.width;
size = Extent3D{
@@ -128,16 +124,15 @@ ImageInfo::ImageInfo(const Maxwell3D::Regs& regs, size_t index) noexcept {
}
size.width = rt.width;
size.height = rt.height;
layer_stride = rt.array_pitch * 4;
layer_stride = rt.layer_stride * 4;
maybe_unaligned_layer_stride = layer_stride;
num_samples = NumSamples(regs.anti_alias_samples_mode);
num_samples = NumSamples(regs.multisample_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.dim_control ==
Maxwell3D::Regs::TileMode::DimensionControl::DepthDefinesDepth) {
if (rt.tile_mode.is_3d) {
type = ImageType::e3D;
size.depth = rt.depth;
} else {
@@ -151,37 +146,31 @@ ImageInfo::ImageInfo(const Maxwell3D::Regs& regs, size_t index) noexcept {
ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept {
format = VideoCore::Surface::PixelFormatFromDepthFormat(regs.zeta.format);
size.width = regs.zeta_size.width;
size.height = regs.zeta_size.height;
size.width = regs.zeta_width;
size.height = regs.zeta_height;
rescaleable = false;
resources.levels = 1;
layer_stride = regs.zeta.array_pitch * 4;
layer_stride = regs.zeta.layer_stride * 4;
maybe_unaligned_layer_stride = layer_stride;
num_samples = NumSamples(regs.anti_alias_samples_mode);
num_samples = NumSamples(regs.multisample_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.dim_control ==
Maxwell3D::Regs::TileMode::DimensionControl::DepthDefinesArray);
ASSERT(regs.zeta.tile_mode.is_3d == 0);
type = ImageType::Linear;
pitch = size.width * BytesPerBlock(format);
} else if (regs.zeta.tile_mode.dim_control ==
Maxwell3D::Regs::TileMode::DimensionControl::DepthDefinesDepth) {
} else if (regs.zeta.tile_mode.is_3d) {
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_size.depth;
size.depth = regs.zeta_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_size.depth;
resources.layers = regs.zeta_depth;
}
}

View File

@@ -189,16 +189,15 @@ typename P::Sampler* TextureCache<P>::GetComputeSampler(u32 index) {
template <class P>
void TextureCache<P>::SynchronizeGraphicsDescriptors() {
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(),
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(),
tsc_limit)) {
channel_state->graphics_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
}
if (channel_state->graphics_image_table.Synchornize(maxwell3d->regs.tex_header.Address(),
tic_limit)) {
if (channel_state->graphics_image_table.Synchornize(maxwell3d->regs.tic.Address(), tic_limit)) {
channel_state->graphics_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
}
}
@@ -353,8 +352,8 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
down_shift = Settings::values.resolution_info.down_shift;
}
render_targets.size = Extent2D{
(maxwell3d->regs.surface_clip.width * up_scale) >> down_shift,
(maxwell3d->regs.surface_clip.height * up_scale) >> down_shift,
(maxwell3d->regs.render_area.width * up_scale) >> down_shift,
(maxwell3d->regs.render_area.height * up_scale) >> down_shift,
};
render_targets.is_rescaled = is_rescaling;
@@ -1981,7 +1980,7 @@ bool TextureCache<P>::IsFullClear(ImageViewId id) {
// Images with multiple resources can't be cleared in a single call
return false;
}
if (regs.clear_control.use_scissor == 0) {
if (regs.clear_flags.scissor == 0) {
// If scissor testing is disabled, the clear is always full
return true;
}

View File

@@ -15,51 +15,51 @@ namespace VideoCommon {
std::vector<Shader::TransformFeedbackVarying> MakeTransformFeedbackVaryings(
const TransformFeedbackState& state) {
static constexpr std::array VECTORS{
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]
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]
};
std::vector<Shader::TransformFeedbackVarying> xfb(256);
for (size_t buffer = 0; buffer < state.layouts.size(); ++buffer) {
@@ -68,20 +68,8 @@ std::vector<Shader::TransformFeedbackVarying> MakeTransformFeedbackVaryings(
const u32 varying_count = layout.varying_count;
u32 highest = 0;
for (u32 offset = 0; offset < varying_count; ++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;
};
const u32 base_offset = offset;
const u8 location = locations[offset];
UNIMPLEMENTED_IF_MSG(layout.stream != 0, "Stream is not zero: {}", layout.stream);
Shader::TransformFeedbackVarying varying{
@@ -90,18 +78,16 @@ std::vector<Shader::TransformFeedbackVarying> MakeTransformFeedbackVaryings(
.offset = offset * 4,
.components = 1,
};
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);
if (std::ranges::find(VECTORS, Common::AlignDown(location, 4)) != VECTORS.end()) {
UNIMPLEMENTED_IF_MSG(location % 4 != 0, "Unaligned TFB");
const auto base_index = attribute / 4;
while (offset + 1 < varying_count && base_index == get_attribute(offset + 1) / 4) {
const u8 base_index = location / 4;
while (offset + 1 < varying_count && base_index == locations[offset + 1] / 4) {
++offset;
++varying.components;
}
}
xfb[attribute] = varying;
xfb[location] = varying;
highest = std::max(highest, (base_offset + varying.components) * 4);
}
UNIMPLEMENTED_IF(highest != layout.stride);

View File

@@ -19,8 +19,7 @@ struct TransformFeedbackState {
u32 stride;
};
std::array<Layout, Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers> layouts;
std::array<std::array<Tegra::Engines::Maxwell3D::Regs::StreamOutLayout, 32>,
Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers>
std::array<std::array<u8, 128>, Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers>
varyings;
};

View File

@@ -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());
}

View File

@@ -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