30fcdc5474
* vk_platform: Check if library was loaded * pica_to_vk: Dont crash on unknow blend equation
220 lines
8.9 KiB
C++
220 lines
8.9 KiB
C++
// Copyright 2023 Citra Emulator Project
|
|
// Licensed under GPLv2 or any later version
|
|
// Refer to the license.txt file included.
|
|
|
|
#pragma once
|
|
|
|
#include "common/logging/log.h"
|
|
#include "core/core.h"
|
|
#include "core/telemetry_session.h"
|
|
#include "video_core/regs.h"
|
|
#include "video_core/renderer_vulkan/vk_common.h"
|
|
|
|
namespace PicaToVK {
|
|
|
|
using TextureFilter = Pica::TexturingRegs::TextureConfig::TextureFilter;
|
|
|
|
inline vk::Filter TextureFilterMode(TextureFilter mode) {
|
|
switch (mode) {
|
|
case TextureFilter::Linear:
|
|
return vk::Filter::eLinear;
|
|
case TextureFilter::Nearest:
|
|
return vk::Filter::eNearest;
|
|
default:
|
|
UNIMPLEMENTED_MSG("Unknown texture filtering mode {}", mode);
|
|
}
|
|
|
|
return vk::Filter::eLinear;
|
|
}
|
|
|
|
inline vk::SamplerMipmapMode TextureMipFilterMode(TextureFilter mip) {
|
|
switch (mip) {
|
|
case TextureFilter::Linear:
|
|
return vk::SamplerMipmapMode::eLinear;
|
|
case TextureFilter::Nearest:
|
|
return vk::SamplerMipmapMode::eNearest;
|
|
default:
|
|
UNIMPLEMENTED_MSG("Unknown texture mipmap filtering mode {}", mip);
|
|
}
|
|
|
|
return vk::SamplerMipmapMode::eLinear;
|
|
}
|
|
|
|
inline vk::SamplerAddressMode WrapMode(Pica::TexturingRegs::TextureConfig::WrapMode mode) {
|
|
static constexpr std::array<vk::SamplerAddressMode, 8> wrap_mode_table{{
|
|
vk::SamplerAddressMode::eClampToEdge,
|
|
vk::SamplerAddressMode::eClampToBorder,
|
|
vk::SamplerAddressMode::eRepeat,
|
|
vk::SamplerAddressMode::eMirroredRepeat,
|
|
// TODO(wwylele): ClampToEdge2 and ClampToBorder2 are not properly implemented here. See the
|
|
// comments in enum WrapMode.
|
|
vk::SamplerAddressMode::eClampToEdge,
|
|
vk::SamplerAddressMode::eClampToBorder,
|
|
vk::SamplerAddressMode::eRepeat,
|
|
vk::SamplerAddressMode::eRepeat,
|
|
}};
|
|
|
|
const auto index = static_cast<std::size_t>(mode);
|
|
ASSERT_MSG(index < wrap_mode_table.size(), "Unknown texture wrap mode {}", index);
|
|
|
|
if (index > 3) {
|
|
Core::System::GetInstance().TelemetrySession().AddField(
|
|
Common::Telemetry::FieldType::Session, "VideoCore_Pica_UnsupportedTextureWrapMode",
|
|
static_cast<u32>(index));
|
|
LOG_WARNING(Render_Vulkan, "Using texture wrap mode {}", index);
|
|
}
|
|
|
|
return wrap_mode_table[index];
|
|
}
|
|
|
|
inline vk::BlendOp BlendEquation(Pica::FramebufferRegs::BlendEquation equation) {
|
|
static constexpr std::array<vk::BlendOp, 5> blend_equation_table{{
|
|
vk::BlendOp::eAdd,
|
|
vk::BlendOp::eSubtract,
|
|
vk::BlendOp::eReverseSubtract,
|
|
vk::BlendOp::eMin,
|
|
vk::BlendOp::eMax,
|
|
}};
|
|
|
|
const auto index = static_cast<std::size_t>(equation);
|
|
if (index >= blend_equation_table.size()) {
|
|
LOG_CRITICAL(Render_Vulkan, "Unknown blend equation {}", index);
|
|
|
|
// This return value is hwtested, not just a stub
|
|
return vk::BlendOp::eAdd;
|
|
}
|
|
return blend_equation_table[index];
|
|
}
|
|
|
|
inline vk::BlendFactor BlendFunc(Pica::FramebufferRegs::BlendFactor factor) {
|
|
static constexpr std::array<vk::BlendFactor, 15> blend_func_table{{
|
|
vk::BlendFactor::eZero, // BlendFactor::Zero
|
|
vk::BlendFactor::eOne, // BlendFactor::One
|
|
vk::BlendFactor::eSrcColor, // BlendFactor::SourceColor
|
|
vk::BlendFactor::eOneMinusSrcColor, // BlendFactor::OneMinusSourceColor
|
|
vk::BlendFactor::eDstColor, // BlendFactor::DestColor
|
|
vk::BlendFactor::eOneMinusDstColor, // BlendFactor::OneMinusDestColor
|
|
vk::BlendFactor::eSrcAlpha, // BlendFactor::SourceAlpha
|
|
vk::BlendFactor::eOneMinusSrcAlpha, // BlendFactor::OneMinusSourceAlpha
|
|
vk::BlendFactor::eDstAlpha, // BlendFactor::DestAlpha
|
|
vk::BlendFactor::eOneMinusDstAlpha, // BlendFactor::OneMinusDestAlpha
|
|
vk::BlendFactor::eConstantColor, // BlendFactor::ConstantColor
|
|
vk::BlendFactor::eOneMinusConstantColor, // BlendFactor::OneMinusConstantColor
|
|
vk::BlendFactor::eConstantAlpha, // BlendFactor::ConstantAlpha
|
|
vk::BlendFactor::eOneMinusConstantAlpha, // BlendFactor::OneMinusConstantAlpha
|
|
vk::BlendFactor::eSrcAlphaSaturate, // BlendFactor::SourceAlphaSaturate
|
|
}};
|
|
|
|
const auto index = static_cast<std::size_t>(factor);
|
|
ASSERT_MSG(index < blend_func_table.size(), "Unknown blend factor {}", index);
|
|
return blend_func_table[index];
|
|
}
|
|
|
|
inline vk::LogicOp LogicOp(Pica::FramebufferRegs::LogicOp op) {
|
|
static constexpr std::array<vk::LogicOp, 16> logic_op_table{{
|
|
vk::LogicOp::eClear, // Clear
|
|
vk::LogicOp::eAnd, // And
|
|
vk::LogicOp::eAndReverse, // AndReverse
|
|
vk::LogicOp::eCopy, // Copy
|
|
vk::LogicOp::eSet, // Set
|
|
vk::LogicOp::eCopyInverted, // CopyInverted
|
|
vk::LogicOp::eNoOp, // NoOp
|
|
vk::LogicOp::eInvert, // Invert
|
|
vk::LogicOp::eNand, // Nand
|
|
vk::LogicOp::eOr, // Or
|
|
vk::LogicOp::eNor, // Nor
|
|
vk::LogicOp::eXor, // Xor
|
|
vk::LogicOp::eEquivalent, // Equiv
|
|
vk::LogicOp::eAndInverted, // AndInverted
|
|
vk::LogicOp::eOrReverse, // OrReverse
|
|
vk::LogicOp::eOrInverted, // OrInverted
|
|
}};
|
|
|
|
const auto index = static_cast<std::size_t>(op);
|
|
ASSERT_MSG(index < logic_op_table.size(), "Unknown logic op {}", index);
|
|
return logic_op_table[index];
|
|
}
|
|
|
|
inline vk::CompareOp CompareFunc(Pica::FramebufferRegs::CompareFunc func) {
|
|
static constexpr std::array<vk::CompareOp, 8> compare_func_table{{
|
|
vk::CompareOp::eNever, // CompareFunc::Never
|
|
vk::CompareOp::eAlways, // CompareFunc::Always
|
|
vk::CompareOp::eEqual, // CompareFunc::Equal
|
|
vk::CompareOp::eNotEqual, // CompareFunc::NotEqual
|
|
vk::CompareOp::eLess, // CompareFunc::LessThan
|
|
vk::CompareOp::eLessOrEqual, // CompareFunc::LessThanOrEqual
|
|
vk::CompareOp::eGreater, // CompareFunc::GreaterThan
|
|
vk::CompareOp::eGreaterOrEqual, // CompareFunc::GreaterThanOrEqual
|
|
}};
|
|
|
|
const auto index = static_cast<std::size_t>(func);
|
|
ASSERT_MSG(index < compare_func_table.size(), "Unknown compare function {}", index);
|
|
return compare_func_table[index];
|
|
}
|
|
|
|
inline vk::StencilOp StencilOp(Pica::FramebufferRegs::StencilAction action) {
|
|
static constexpr std::array<vk::StencilOp, 8> stencil_op_table{{
|
|
vk::StencilOp::eKeep, // StencilAction::Keep
|
|
vk::StencilOp::eZero, // StencilAction::Zero
|
|
vk::StencilOp::eReplace, // StencilAction::Replace
|
|
vk::StencilOp::eIncrementAndClamp, // StencilAction::Increment
|
|
vk::StencilOp::eDecrementAndClamp, // StencilAction::Decrement
|
|
vk::StencilOp::eInvert, // StencilAction::Invert
|
|
vk::StencilOp::eIncrementAndWrap, // StencilAction::IncrementWrap
|
|
vk::StencilOp::eDecrementAndWrap, // StencilAction::DecrementWrap
|
|
}};
|
|
|
|
const auto index = static_cast<std::size_t>(action);
|
|
ASSERT_MSG(index < stencil_op_table.size(), "Unknown stencil op {}", index);
|
|
return stencil_op_table[index];
|
|
}
|
|
|
|
inline vk::PrimitiveTopology PrimitiveTopology(Pica::PipelineRegs::TriangleTopology topology) {
|
|
switch (topology) {
|
|
case Pica::PipelineRegs::TriangleTopology::Fan:
|
|
return vk::PrimitiveTopology::eTriangleFan;
|
|
case Pica::PipelineRegs::TriangleTopology::List:
|
|
case Pica::PipelineRegs::TriangleTopology::Shader:
|
|
return vk::PrimitiveTopology::eTriangleList;
|
|
case Pica::PipelineRegs::TriangleTopology::Strip:
|
|
return vk::PrimitiveTopology::eTriangleStrip;
|
|
default:
|
|
UNREACHABLE_MSG("Unknown triangle topology {}", topology);
|
|
}
|
|
return vk::PrimitiveTopology::eTriangleList;
|
|
}
|
|
|
|
inline vk::CullModeFlags CullMode(Pica::RasterizerRegs::CullMode mode) {
|
|
switch (mode) {
|
|
case Pica::RasterizerRegs::CullMode::KeepAll:
|
|
return vk::CullModeFlagBits::eNone;
|
|
case Pica::RasterizerRegs::CullMode::KeepClockWise:
|
|
case Pica::RasterizerRegs::CullMode::KeepCounterClockWise:
|
|
return vk::CullModeFlagBits::eBack;
|
|
default:
|
|
UNREACHABLE_MSG("Unknown cull mode {}", mode);
|
|
}
|
|
return vk::CullModeFlagBits::eNone;
|
|
}
|
|
|
|
inline vk::FrontFace FrontFace(Pica::RasterizerRegs::CullMode mode) {
|
|
switch (mode) {
|
|
case Pica::RasterizerRegs::CullMode::KeepAll:
|
|
case Pica::RasterizerRegs::CullMode::KeepClockWise:
|
|
return vk::FrontFace::eCounterClockwise;
|
|
case Pica::RasterizerRegs::CullMode::KeepCounterClockWise:
|
|
return vk::FrontFace::eClockwise;
|
|
default:
|
|
UNREACHABLE_MSG("Unknown cull mode {}", mode);
|
|
}
|
|
return vk::FrontFace::eClockwise;
|
|
}
|
|
|
|
inline Common::Vec4f ColorRGBA8(const u32 color) {
|
|
const auto rgba =
|
|
Common::Vec4u{color >> 0 & 0xFF, color >> 8 & 0xFF, color >> 16 & 0xFF, color >> 24 & 0xFF};
|
|
return rgba / 255.0f;
|
|
}
|
|
|
|
} // namespace PicaToVK
|