mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-22 18:15:14 +00:00
Merge branch 'shadps4-emu:main' into volume-slider
This commit is contained in:
commit
602b2c3ee3
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
|
#include "common/elf_info.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/polyfill_thread.h"
|
#include "common/polyfill_thread.h"
|
||||||
#include "common/thread.h"
|
#include "common/thread.h"
|
||||||
@ -243,6 +244,19 @@ s32 PS4_SYSV_ABI sceKernelSetGPO() {
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceKernelGetSystemSwVersion(SwVersionStruct* ret) {
|
||||||
|
if (ret == nullptr) {
|
||||||
|
return ORBIS_OK; // but why?
|
||||||
|
}
|
||||||
|
ASSERT(ret->struct_size == 40);
|
||||||
|
u32 fake_fw = Common::ElfInfo::Instance().RawFirmwareVer();
|
||||||
|
ret->hex_representation = fake_fw;
|
||||||
|
std::snprintf(ret->text_representation, 28, "%2x.%03x.%03x", fake_fw >> 0x18,
|
||||||
|
fake_fw >> 0xc & 0xfff, fake_fw & 0xfff); // why %2x?
|
||||||
|
LOG_INFO(Lib_Kernel, "called, returned sw version: {}", ret->text_representation);
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
|
void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
|
||||||
service_thread = std::jthread{KernelServiceThread};
|
service_thread = std::jthread{KernelServiceThread};
|
||||||
|
|
||||||
@ -258,6 +272,7 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
|
|||||||
Libraries::Kernel::RegisterDebug(sym);
|
Libraries::Kernel::RegisterDebug(sym);
|
||||||
|
|
||||||
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
|
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
|
||||||
|
LIB_FUNCTION("Mv1zUObHvXI", "libkernel", 1, "libkernel", 1, 1, sceKernelGetSystemSwVersion);
|
||||||
LIB_FUNCTION("PfccT7qURYE", "libkernel", 1, "libkernel", 1, 1, kernel_ioctl);
|
LIB_FUNCTION("PfccT7qURYE", "libkernel", 1, "libkernel", 1, 1, kernel_ioctl);
|
||||||
LIB_FUNCTION("JGfTMBOdUJo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetFsSandboxRandomWord);
|
LIB_FUNCTION("JGfTMBOdUJo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetFsSandboxRandomWord);
|
||||||
LIB_FUNCTION("6xVpy0Fdq+I", "libkernel", 1, "libkernel", 1, 1, _sigprocmask);
|
LIB_FUNCTION("6xVpy0Fdq+I", "libkernel", 1, "libkernel", 1, 1, _sigprocmask);
|
||||||
|
@ -35,6 +35,12 @@ struct OrbisWrapperImpl<PS4_SYSV_ABI R (*)(Args...), f> {
|
|||||||
|
|
||||||
s32* PS4_SYSV_ABI __Error();
|
s32* PS4_SYSV_ABI __Error();
|
||||||
|
|
||||||
|
struct SwVersionStruct {
|
||||||
|
u64 struct_size;
|
||||||
|
char text_representation[0x1c];
|
||||||
|
u32 hex_representation;
|
||||||
|
};
|
||||||
|
|
||||||
void RegisterKernel(Core::Loader::SymbolsResolver* sym);
|
void RegisterKernel(Core::Loader::SymbolsResolver* sym);
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
@ -537,6 +537,7 @@ u64 MemoryManager::UnmapBytesFromEntry(VAddr virtual_addr, VirtualMemoryArea vma
|
|||||||
vma_base_size - start_in_vma < size ? vma_base_size - start_in_vma : size;
|
vma_base_size - start_in_vma < size ? vma_base_size - start_in_vma : size;
|
||||||
const bool has_backing = type == VMAType::Direct || type == VMAType::File;
|
const bool has_backing = type == VMAType::Direct || type == VMAType::File;
|
||||||
const auto prot = vma_base.prot;
|
const auto prot = vma_base.prot;
|
||||||
|
const bool readonly_file = prot == MemoryProt::CpuRead && type == VMAType::File;
|
||||||
|
|
||||||
if (type == VMAType::Free) {
|
if (type == VMAType::Free) {
|
||||||
return adjusted_size;
|
return adjusted_size;
|
||||||
@ -554,9 +555,8 @@ u64 MemoryManager::UnmapBytesFromEntry(VAddr virtual_addr, VirtualMemoryArea vma
|
|||||||
vma.phys_base = 0;
|
vma.phys_base = 0;
|
||||||
vma.disallow_merge = false;
|
vma.disallow_merge = false;
|
||||||
vma.name = "";
|
vma.name = "";
|
||||||
const auto post_merge_it = MergeAdjacent(vma_map, new_it);
|
MergeAdjacent(vma_map, new_it);
|
||||||
auto& post_merge_vma = post_merge_it->second;
|
|
||||||
bool readonly_file = post_merge_vma.prot == MemoryProt::CpuRead && type == VMAType::File;
|
|
||||||
if (type != VMAType::Reserved && type != VMAType::PoolReserved) {
|
if (type != VMAType::Reserved && type != VMAType::PoolReserved) {
|
||||||
// If this mapping has GPU access, unmap from GPU.
|
// If this mapping has GPU access, unmap from GPU.
|
||||||
if (IsValidGpuMapping(virtual_addr, size)) {
|
if (IsValidGpuMapping(virtual_addr, size)) {
|
||||||
|
@ -304,6 +304,14 @@ struct Liverpool {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LineControl {
|
||||||
|
u32 width_fixed_point;
|
||||||
|
|
||||||
|
float Width() const {
|
||||||
|
return static_cast<float>(width_fixed_point) / 8.0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct ModeControl {
|
struct ModeControl {
|
||||||
s32 msaa_enable : 1;
|
s32 msaa_enable : 1;
|
||||||
s32 vport_scissor_enable : 1;
|
s32 vport_scissor_enable : 1;
|
||||||
@ -513,9 +521,16 @@ struct Liverpool {
|
|||||||
BitField<19, 1, ClipSpace> clip_space;
|
BitField<19, 1, ClipSpace> clip_space;
|
||||||
BitField<21, 1, PrimKillCond> vtx_kill_or;
|
BitField<21, 1, PrimKillCond> vtx_kill_or;
|
||||||
BitField<22, 1, u32> dx_rasterization_kill;
|
BitField<22, 1, u32> dx_rasterization_kill;
|
||||||
BitField<23, 1, u32> dx_linear_attr_clip_enable;
|
BitField<24, 1, u32> dx_linear_attr_clip_enable;
|
||||||
BitField<26, 1, u32> zclip_near_disable;
|
BitField<26, 1, u32> zclip_near_disable;
|
||||||
BitField<26, 1, u32> zclip_far_disable;
|
BitField<27, 1, u32> zclip_far_disable;
|
||||||
|
|
||||||
|
bool ZclipEnable() const {
|
||||||
|
if (zclip_near_disable != zclip_far_disable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !zclip_near_disable;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class PolygonMode : u32 {
|
enum class PolygonMode : u32 {
|
||||||
@ -738,12 +753,7 @@ struct Liverpool {
|
|||||||
u32 data_w;
|
u32 data_w;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BlendConstants {
|
using BlendConstants = std::array<float, 4>;
|
||||||
float red;
|
|
||||||
float green;
|
|
||||||
float blue;
|
|
||||||
float alpha;
|
|
||||||
};
|
|
||||||
|
|
||||||
union BlendControl {
|
union BlendControl {
|
||||||
enum class BlendFactor : u32 {
|
enum class BlendFactor : u32 {
|
||||||
@ -796,11 +806,29 @@ struct Liverpool {
|
|||||||
Err = 4u,
|
Err = 4u,
|
||||||
FmaskDecompress = 5u,
|
FmaskDecompress = 5u,
|
||||||
};
|
};
|
||||||
|
enum class LogicOp : u32 {
|
||||||
|
Clear = 0x00,
|
||||||
|
Nor = 0x11,
|
||||||
|
AndInverted = 0x22,
|
||||||
|
CopyInverted = 0x33,
|
||||||
|
AndReverse = 0x44,
|
||||||
|
Invert = 0x55,
|
||||||
|
Xor = 0x66,
|
||||||
|
Nand = 0x77,
|
||||||
|
And = 0x88,
|
||||||
|
Equiv = 0x99,
|
||||||
|
Noop = 0xAA,
|
||||||
|
OrInverted = 0xBB,
|
||||||
|
Copy = 0xCC,
|
||||||
|
OrReverse = 0xDD,
|
||||||
|
Or = 0xEE,
|
||||||
|
Set = 0xFF,
|
||||||
|
};
|
||||||
|
|
||||||
BitField<0, 1, u32> disable_dual_quad;
|
BitField<0, 1, u32> disable_dual_quad;
|
||||||
BitField<3, 1, u32> degamma_enable;
|
BitField<3, 1, u32> degamma_enable;
|
||||||
BitField<4, 3, OperationMode> mode;
|
BitField<4, 3, OperationMode> mode;
|
||||||
BitField<16, 8, u32> rop3;
|
BitField<16, 8, LogicOp> rop3;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ColorBuffer {
|
struct ColorBuffer {
|
||||||
@ -1369,7 +1397,9 @@ struct Liverpool {
|
|||||||
PolygonControl polygon_control;
|
PolygonControl polygon_control;
|
||||||
ViewportControl viewport_control;
|
ViewportControl viewport_control;
|
||||||
VsOutputControl vs_output_control;
|
VsOutputControl vs_output_control;
|
||||||
INSERT_PADDING_WORDS(0xA287 - 0xA207 - 1);
|
INSERT_PADDING_WORDS(0xA287 - 0xA207 - 6);
|
||||||
|
LineControl line_control;
|
||||||
|
INSERT_PADDING_WORDS(4);
|
||||||
HsTessFactorClamp hs_clamp;
|
HsTessFactorClamp hs_clamp;
|
||||||
INSERT_PADDING_WORDS(0xA290 - 0xA287 - 2);
|
INSERT_PADDING_WORDS(0xA290 - 0xA287 - 2);
|
||||||
GsMode vgt_gs_mode;
|
GsMode vgt_gs_mode;
|
||||||
@ -1695,6 +1725,7 @@ static_assert(GFX6_3D_REG_INDEX(color_control) == 0xA202);
|
|||||||
static_assert(GFX6_3D_REG_INDEX(clipper_control) == 0xA204);
|
static_assert(GFX6_3D_REG_INDEX(clipper_control) == 0xA204);
|
||||||
static_assert(GFX6_3D_REG_INDEX(viewport_control) == 0xA206);
|
static_assert(GFX6_3D_REG_INDEX(viewport_control) == 0xA206);
|
||||||
static_assert(GFX6_3D_REG_INDEX(vs_output_control) == 0xA207);
|
static_assert(GFX6_3D_REG_INDEX(vs_output_control) == 0xA207);
|
||||||
|
static_assert(GFX6_3D_REG_INDEX(line_control) == 0xA282);
|
||||||
static_assert(GFX6_3D_REG_INDEX(hs_clamp) == 0xA287);
|
static_assert(GFX6_3D_REG_INDEX(hs_clamp) == 0xA287);
|
||||||
static_assert(GFX6_3D_REG_INDEX(vgt_gs_mode) == 0xA290);
|
static_assert(GFX6_3D_REG_INDEX(vgt_gs_mode) == 0xA290);
|
||||||
static_assert(GFX6_3D_REG_INDEX(mode_control) == 0xA292);
|
static_assert(GFX6_3D_REG_INDEX(mode_control) == 0xA292);
|
||||||
|
@ -245,6 +245,46 @@ vk::BlendOp BlendOp(Liverpool::BlendControl::BlendFunc func) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vk::LogicOp LogicOp(Liverpool::ColorControl::LogicOp logic_op) {
|
||||||
|
using LogicOp = Liverpool::ColorControl::LogicOp;
|
||||||
|
switch (logic_op) {
|
||||||
|
case LogicOp::Clear:
|
||||||
|
return vk::LogicOp::eClear;
|
||||||
|
case LogicOp::Nor:
|
||||||
|
return vk::LogicOp::eNor;
|
||||||
|
case LogicOp::AndInverted:
|
||||||
|
return vk::LogicOp::eAndInverted;
|
||||||
|
case LogicOp::CopyInverted:
|
||||||
|
return vk::LogicOp::eCopyInverted;
|
||||||
|
case LogicOp::AndReverse:
|
||||||
|
return vk::LogicOp::eAndReverse;
|
||||||
|
case LogicOp::Invert:
|
||||||
|
return vk::LogicOp::eInvert;
|
||||||
|
case LogicOp::Xor:
|
||||||
|
return vk::LogicOp::eXor;
|
||||||
|
case LogicOp::Nand:
|
||||||
|
return vk::LogicOp::eNand;
|
||||||
|
case LogicOp::And:
|
||||||
|
return vk::LogicOp::eAnd;
|
||||||
|
case LogicOp::Equiv:
|
||||||
|
return vk::LogicOp::eEquivalent;
|
||||||
|
case LogicOp::Noop:
|
||||||
|
return vk::LogicOp::eNoOp;
|
||||||
|
case LogicOp::OrInverted:
|
||||||
|
return vk::LogicOp::eOrInverted;
|
||||||
|
case LogicOp::Copy:
|
||||||
|
return vk::LogicOp::eCopy;
|
||||||
|
case LogicOp::OrReverse:
|
||||||
|
return vk::LogicOp::eOrReverse;
|
||||||
|
case LogicOp::Or:
|
||||||
|
return vk::LogicOp::eOr;
|
||||||
|
case LogicOp::Set:
|
||||||
|
return vk::LogicOp::eSet;
|
||||||
|
default:
|
||||||
|
UNREACHABLE_MSG("Unknown logic op {}", u32(logic_op));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// https://github.com/chaotic-cx/mesa-mirror/blob/0954afff5/src/amd/vulkan/radv_sampler.c#L21
|
// https://github.com/chaotic-cx/mesa-mirror/blob/0954afff5/src/amd/vulkan/radv_sampler.c#L21
|
||||||
vk::SamplerAddressMode ClampMode(AmdGpu::ClampMode mode) {
|
vk::SamplerAddressMode ClampMode(AmdGpu::ClampMode mode) {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
|
@ -34,6 +34,8 @@ bool IsDualSourceBlendFactor(Liverpool::BlendControl::BlendFactor factor);
|
|||||||
|
|
||||||
vk::BlendOp BlendOp(Liverpool::BlendControl::BlendFunc func);
|
vk::BlendOp BlendOp(Liverpool::BlendControl::BlendFunc func);
|
||||||
|
|
||||||
|
vk::LogicOp LogicOp(Liverpool::ColorControl::LogicOp logic_op);
|
||||||
|
|
||||||
vk::SamplerAddressMode ClampMode(AmdGpu::ClampMode mode);
|
vk::SamplerAddressMode ClampMode(AmdGpu::ClampMode mode);
|
||||||
|
|
||||||
vk::CompareOp DepthCompare(AmdGpu::DepthCompare comp);
|
vk::CompareOp DepthCompare(AmdGpu::DepthCompare comp);
|
||||||
|
@ -109,28 +109,63 @@ GraphicsPipeline::GraphicsPipeline(
|
|||||||
.patchControlPoints = is_rect_list ? 3U : (is_quad_list ? 4U : key.patch_control_points),
|
.patchControlPoints = is_rect_list ? 3U : (is_quad_list ? 4U : key.patch_control_points),
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::PipelineRasterizationStateCreateInfo raster_state = {
|
vk::StructureChain raster_chain = {
|
||||||
.depthClampEnable = false,
|
vk::PipelineRasterizationStateCreateInfo{
|
||||||
.rasterizerDiscardEnable = false,
|
.depthClampEnable = key.depth_clamp_enable ||
|
||||||
.polygonMode = LiverpoolToVK::PolygonMode(key.polygon_mode),
|
(!key.depth_clip_enable && !instance.IsDepthClipEnableSupported()),
|
||||||
.lineWidth = 1.0f,
|
.rasterizerDiscardEnable = false,
|
||||||
|
.polygonMode = LiverpoolToVK::PolygonMode(key.polygon_mode),
|
||||||
|
.lineWidth = 1.0f,
|
||||||
|
},
|
||||||
|
vk::PipelineRasterizationProvokingVertexStateCreateInfoEXT{
|
||||||
|
.provokingVertexMode = key.provoking_vtx_last == Liverpool::ProvokingVtxLast::First
|
||||||
|
? vk::ProvokingVertexModeEXT::eFirstVertex
|
||||||
|
: vk::ProvokingVertexModeEXT::eLastVertex,
|
||||||
|
},
|
||||||
|
vk::PipelineRasterizationDepthClipStateCreateInfoEXT{
|
||||||
|
.depthClipEnable = key.depth_clip_enable,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!instance.IsProvokingVertexSupported()) {
|
||||||
|
raster_chain.unlink<vk::PipelineRasterizationProvokingVertexStateCreateInfoEXT>();
|
||||||
|
}
|
||||||
|
if (!instance.IsDepthClipEnableSupported()) {
|
||||||
|
raster_chain.unlink<vk::PipelineRasterizationDepthClipStateCreateInfoEXT>();
|
||||||
|
}
|
||||||
|
|
||||||
const vk::PipelineMultisampleStateCreateInfo multisampling = {
|
const vk::PipelineMultisampleStateCreateInfo multisampling = {
|
||||||
.rasterizationSamples =
|
.rasterizationSamples =
|
||||||
LiverpoolToVK::NumSamples(key.num_samples, instance.GetFramebufferSampleCounts()),
|
LiverpoolToVK::NumSamples(key.num_samples, instance.GetFramebufferSampleCounts()),
|
||||||
.sampleShadingEnable = false,
|
.sampleShadingEnable = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::PipelineViewportDepthClipControlCreateInfoEXT clip_control = {
|
const vk::DepthClampRangeEXT depth_clamp_range = {
|
||||||
.negativeOneToOne = key.clip_space == Liverpool::ClipSpace::MinusWToW,
|
.minDepthClamp = key.min_depth_clamp,
|
||||||
|
.maxDepthClamp = key.max_depth_clamp,
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::PipelineViewportStateCreateInfo viewport_info = {
|
vk::StructureChain viewport_chain = {
|
||||||
.pNext = instance.IsDepthClipControlSupported() ? &clip_control : nullptr,
|
vk::PipelineViewportStateCreateInfo{},
|
||||||
|
vk::PipelineViewportDepthClipControlCreateInfoEXT{
|
||||||
|
.negativeOneToOne = key.clip_space == Liverpool::ClipSpace::MinusWToW,
|
||||||
|
},
|
||||||
|
vk::PipelineViewportDepthClampControlCreateInfoEXT{
|
||||||
|
.depthClampMode = key.depth_clamp_user_defined_range
|
||||||
|
? vk::DepthClampModeEXT::eUserDefinedRange
|
||||||
|
: vk::DepthClampModeEXT::eViewportRange,
|
||||||
|
.pDepthClampRange = &depth_clamp_range,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::container::static_vector<vk::DynamicState, 20> dynamic_states = {
|
if (!instance.IsDepthClampControlSupported()) {
|
||||||
|
viewport_chain.unlink<vk::PipelineViewportDepthClampControlCreateInfoEXT>();
|
||||||
|
}
|
||||||
|
if (!instance.IsDepthClipControlSupported()) {
|
||||||
|
viewport_chain.unlink<vk::PipelineViewportDepthClipControlCreateInfoEXT>();
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::container::static_vector<vk::DynamicState, 32> dynamic_states = {
|
||||||
vk::DynamicState::eViewportWithCount, vk::DynamicState::eScissorWithCount,
|
vk::DynamicState::eViewportWithCount, vk::DynamicState::eScissorWithCount,
|
||||||
vk::DynamicState::eBlendConstants, vk::DynamicState::eDepthTestEnable,
|
vk::DynamicState::eBlendConstants, vk::DynamicState::eDepthTestEnable,
|
||||||
vk::DynamicState::eDepthWriteEnable, vk::DynamicState::eDepthCompareOp,
|
vk::DynamicState::eDepthWriteEnable, vk::DynamicState::eDepthCompareOp,
|
||||||
@ -138,7 +173,8 @@ GraphicsPipeline::GraphicsPipeline(
|
|||||||
vk::DynamicState::eStencilTestEnable, vk::DynamicState::eStencilReference,
|
vk::DynamicState::eStencilTestEnable, vk::DynamicState::eStencilReference,
|
||||||
vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask,
|
vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask,
|
||||||
vk::DynamicState::eStencilOp, vk::DynamicState::eCullMode,
|
vk::DynamicState::eStencilOp, vk::DynamicState::eCullMode,
|
||||||
vk::DynamicState::eFrontFace,
|
vk::DynamicState::eFrontFace, vk::DynamicState::eRasterizerDiscardEnable,
|
||||||
|
vk::DynamicState::eLineWidth,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (instance.IsPrimitiveRestartDisableSupported()) {
|
if (instance.IsPrimitiveRestartDisableSupported()) {
|
||||||
@ -221,11 +257,19 @@ GraphicsPipeline::GraphicsPipeline(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto depth_format =
|
||||||
|
instance.GetSupportedFormat(LiverpoolToVK::DepthFormat(key.z_format, key.stencil_format),
|
||||||
|
vk::FormatFeatureFlagBits2::eDepthStencilAttachment);
|
||||||
const vk::PipelineRenderingCreateInfo pipeline_rendering_ci = {
|
const vk::PipelineRenderingCreateInfo pipeline_rendering_ci = {
|
||||||
.colorAttachmentCount = key.num_color_attachments,
|
.colorAttachmentCount = key.num_color_attachments,
|
||||||
.pColorAttachmentFormats = key.color_formats.data(),
|
.pColorAttachmentFormats = key.color_formats.data(),
|
||||||
.depthAttachmentFormat = key.depth_format,
|
.depthAttachmentFormat = key.z_format != Liverpool::DepthBuffer::ZFormat::Invalid
|
||||||
.stencilAttachmentFormat = key.stencil_format,
|
? depth_format
|
||||||
|
: vk::Format::eUndefined,
|
||||||
|
.stencilAttachmentFormat =
|
||||||
|
key.stencil_format != Liverpool::DepthBuffer::StencilFormat::Invalid
|
||||||
|
? depth_format
|
||||||
|
: vk::Format::eUndefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<vk::PipelineColorBlendAttachmentState, Liverpool::NumColorBuffers> attachments;
|
std::array<vk::PipelineColorBlendAttachmentState, Liverpool::NumColorBuffers> attachments;
|
||||||
@ -280,8 +324,9 @@ GraphicsPipeline::GraphicsPipeline(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const vk::PipelineColorBlendStateCreateInfo color_blending = {
|
const vk::PipelineColorBlendStateCreateInfo color_blending = {
|
||||||
.logicOpEnable = false,
|
.logicOpEnable =
|
||||||
.logicOp = vk::LogicOp::eCopy,
|
instance.IsLogicOpSupported() && key.logic_op != Liverpool::ColorControl::LogicOp::Copy,
|
||||||
|
.logicOp = LiverpoolToVK::LogicOp(key.logic_op),
|
||||||
.attachmentCount = key.num_color_attachments,
|
.attachmentCount = key.num_color_attachments,
|
||||||
.pAttachments = attachments.data(),
|
.pAttachments = attachments.data(),
|
||||||
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f},
|
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f},
|
||||||
@ -294,8 +339,8 @@ GraphicsPipeline::GraphicsPipeline(
|
|||||||
.pVertexInputState = !instance.IsVertexInputDynamicState() ? &vertex_input_info : nullptr,
|
.pVertexInputState = !instance.IsVertexInputDynamicState() ? &vertex_input_info : nullptr,
|
||||||
.pInputAssemblyState = &input_assembly,
|
.pInputAssemblyState = &input_assembly,
|
||||||
.pTessellationState = &tessellation_state,
|
.pTessellationState = &tessellation_state,
|
||||||
.pViewportState = &viewport_info,
|
.pViewportState = &viewport_chain.get(),
|
||||||
.pRasterizationState = &raster_state,
|
.pRasterizationState = &raster_chain.get(),
|
||||||
.pMultisampleState = &multisampling,
|
.pMultisampleState = &multisampling,
|
||||||
.pColorBlendState = &color_blending,
|
.pColorBlendState = &color_blending,
|
||||||
.pDynamicState = &dynamic_info,
|
.pDynamicState = &dynamic_info,
|
||||||
|
@ -33,22 +33,32 @@ using VertexInputs = boost::container::static_vector<T, MaxVertexBufferCount>;
|
|||||||
|
|
||||||
struct GraphicsPipelineKey {
|
struct GraphicsPipelineKey {
|
||||||
std::array<size_t, MaxShaderStages> stage_hashes;
|
std::array<size_t, MaxShaderStages> stage_hashes;
|
||||||
|
std::array<vk::Format, MaxVertexBufferCount> vertex_buffer_formats;
|
||||||
|
u32 patch_control_points;
|
||||||
u32 num_color_attachments;
|
u32 num_color_attachments;
|
||||||
std::array<vk::Format, Liverpool::NumColorBuffers> color_formats;
|
std::array<vk::Format, Liverpool::NumColorBuffers> color_formats;
|
||||||
std::array<Shader::PsColorBuffer, Liverpool::NumColorBuffers> color_buffers;
|
std::array<Shader::PsColorBuffer, Liverpool::NumColorBuffers> color_buffers;
|
||||||
vk::Format depth_format;
|
|
||||||
vk::Format stencil_format;
|
|
||||||
|
|
||||||
u32 num_samples;
|
|
||||||
u32 mrt_mask;
|
|
||||||
AmdGpu::PrimitiveType prim_type;
|
|
||||||
Liverpool::PolygonMode polygon_mode;
|
|
||||||
Liverpool::ClipSpace clip_space;
|
|
||||||
Liverpool::ColorBufferMask cb_shader_mask;
|
|
||||||
std::array<Liverpool::BlendControl, Liverpool::NumColorBuffers> blend_controls;
|
std::array<Liverpool::BlendControl, Liverpool::NumColorBuffers> blend_controls;
|
||||||
std::array<vk::ColorComponentFlags, Liverpool::NumColorBuffers> write_masks;
|
std::array<vk::ColorComponentFlags, Liverpool::NumColorBuffers> write_masks;
|
||||||
std::array<vk::Format, MaxVertexBufferCount> vertex_buffer_formats;
|
Liverpool::ColorBufferMask cb_shader_mask;
|
||||||
u32 patch_control_points;
|
Liverpool::ColorControl::LogicOp logic_op;
|
||||||
|
u32 num_samples;
|
||||||
|
u32 mrt_mask;
|
||||||
|
struct {
|
||||||
|
Liverpool::DepthBuffer::ZFormat z_format : 2;
|
||||||
|
Liverpool::DepthBuffer::StencilFormat stencil_format : 1;
|
||||||
|
u32 depth_clamp_enable : 1;
|
||||||
|
u32 depth_clamp_user_defined_range : 1;
|
||||||
|
float min_depth_clamp;
|
||||||
|
float max_depth_clamp;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
AmdGpu::PrimitiveType prim_type : 5;
|
||||||
|
Liverpool::PolygonMode polygon_mode : 2;
|
||||||
|
Liverpool::ClipSpace clip_space : 1;
|
||||||
|
Liverpool::ProvokingVtxLast provoking_vtx_last : 1;
|
||||||
|
u32 depth_clip_enable : 1;
|
||||||
|
};
|
||||||
|
|
||||||
bool operator==(const GraphicsPipelineKey& key) const noexcept {
|
bool operator==(const GraphicsPipelineKey& key) const noexcept {
|
||||||
return std::memcmp(this, &key, sizeof(key)) == 0;
|
return std::memcmp(this, &key, sizeof(key)) == 0;
|
||||||
|
@ -270,10 +270,13 @@ bool Instance::CreateDevice() {
|
|||||||
}
|
}
|
||||||
custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||||
depth_clip_control = add_extension(VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
|
depth_clip_control = add_extension(VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
|
||||||
|
depth_clip_enable = add_extension(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME);
|
||||||
|
depth_clamp_control = add_extension(VK_EXT_DEPTH_CLAMP_CONTROL_EXTENSION_NAME);
|
||||||
vertex_input_dynamic_state = add_extension(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
vertex_input_dynamic_state = add_extension(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||||
list_restart = add_extension(VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME);
|
list_restart = add_extension(VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME);
|
||||||
fragment_shader_barycentric = add_extension(VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME);
|
fragment_shader_barycentric = add_extension(VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME);
|
||||||
legacy_vertex_attributes = add_extension(VK_EXT_LEGACY_VERTEX_ATTRIBUTES_EXTENSION_NAME);
|
legacy_vertex_attributes = add_extension(VK_EXT_LEGACY_VERTEX_ATTRIBUTES_EXTENSION_NAME);
|
||||||
|
provoking_vertex = add_extension(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
|
||||||
shader_stencil_export = add_extension(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
|
shader_stencil_export = add_extension(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
|
||||||
image_load_store_lod = add_extension(VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME);
|
image_load_store_lod = add_extension(VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME);
|
||||||
amd_gcn_shader = add_extension(VK_AMD_GCN_SHADER_EXTENSION_NAME);
|
amd_gcn_shader = add_extension(VK_AMD_GCN_SHADER_EXTENSION_NAME);
|
||||||
@ -362,9 +365,11 @@ bool Instance::CreateDevice() {
|
|||||||
.dualSrcBlend = features.dualSrcBlend,
|
.dualSrcBlend = features.dualSrcBlend,
|
||||||
.logicOp = features.logicOp,
|
.logicOp = features.logicOp,
|
||||||
.multiDrawIndirect = features.multiDrawIndirect,
|
.multiDrawIndirect = features.multiDrawIndirect,
|
||||||
|
.depthClamp = features.depthClamp,
|
||||||
.depthBiasClamp = features.depthBiasClamp,
|
.depthBiasClamp = features.depthBiasClamp,
|
||||||
.fillModeNonSolid = features.fillModeNonSolid,
|
.fillModeNonSolid = features.fillModeNonSolid,
|
||||||
.depthBounds = features.depthBounds,
|
.depthBounds = features.depthBounds,
|
||||||
|
.wideLines = features.wideLines,
|
||||||
.multiViewport = features.multiViewport,
|
.multiViewport = features.multiViewport,
|
||||||
.samplerAnisotropy = features.samplerAnisotropy,
|
.samplerAnisotropy = features.samplerAnisotropy,
|
||||||
.vertexPipelineStoresAndAtomics = features.vertexPipelineStoresAndAtomics,
|
.vertexPipelineStoresAndAtomics = features.vertexPipelineStoresAndAtomics,
|
||||||
@ -418,6 +423,12 @@ bool Instance::CreateDevice() {
|
|||||||
vk::PhysicalDeviceDepthClipControlFeaturesEXT{
|
vk::PhysicalDeviceDepthClipControlFeaturesEXT{
|
||||||
.depthClipControl = true,
|
.depthClipControl = true,
|
||||||
},
|
},
|
||||||
|
vk::PhysicalDeviceDepthClipEnableFeaturesEXT{
|
||||||
|
.depthClipEnable = true,
|
||||||
|
},
|
||||||
|
vk::PhysicalDeviceDepthClampControlFeaturesEXT{
|
||||||
|
.depthClampControl = true,
|
||||||
|
},
|
||||||
vk::PhysicalDeviceRobustness2FeaturesEXT{
|
vk::PhysicalDeviceRobustness2FeaturesEXT{
|
||||||
.robustBufferAccess2 = robustness2_features.robustBufferAccess2,
|
.robustBufferAccess2 = robustness2_features.robustBufferAccess2,
|
||||||
.robustImageAccess2 = robustness2_features.robustImageAccess2,
|
.robustImageAccess2 = robustness2_features.robustImageAccess2,
|
||||||
@ -437,6 +448,9 @@ bool Instance::CreateDevice() {
|
|||||||
vk::PhysicalDeviceLegacyVertexAttributesFeaturesEXT{
|
vk::PhysicalDeviceLegacyVertexAttributesFeaturesEXT{
|
||||||
.legacyVertexAttributes = true,
|
.legacyVertexAttributes = true,
|
||||||
},
|
},
|
||||||
|
vk::PhysicalDeviceProvokingVertexFeaturesEXT{
|
||||||
|
.provokingVertexLast = true,
|
||||||
|
},
|
||||||
vk::PhysicalDeviceVertexAttributeDivisorFeatures{
|
vk::PhysicalDeviceVertexAttributeDivisorFeatures{
|
||||||
.vertexAttributeInstanceRateDivisor = true,
|
.vertexAttributeInstanceRateDivisor = true,
|
||||||
},
|
},
|
||||||
@ -487,6 +501,12 @@ bool Instance::CreateDevice() {
|
|||||||
if (!depth_clip_control) {
|
if (!depth_clip_control) {
|
||||||
device_chain.unlink<vk::PhysicalDeviceDepthClipControlFeaturesEXT>();
|
device_chain.unlink<vk::PhysicalDeviceDepthClipControlFeaturesEXT>();
|
||||||
}
|
}
|
||||||
|
if (!depth_clip_enable) {
|
||||||
|
device_chain.unlink<vk::PhysicalDeviceDepthClipEnableFeaturesEXT>();
|
||||||
|
}
|
||||||
|
if (!depth_clamp_control) {
|
||||||
|
device_chain.unlink<vk::PhysicalDeviceDepthClampControlFeaturesEXT>();
|
||||||
|
}
|
||||||
if (!robustness2) {
|
if (!robustness2) {
|
||||||
device_chain.unlink<vk::PhysicalDeviceRobustness2FeaturesEXT>();
|
device_chain.unlink<vk::PhysicalDeviceRobustness2FeaturesEXT>();
|
||||||
}
|
}
|
||||||
@ -502,6 +522,9 @@ bool Instance::CreateDevice() {
|
|||||||
if (!legacy_vertex_attributes) {
|
if (!legacy_vertex_attributes) {
|
||||||
device_chain.unlink<vk::PhysicalDeviceLegacyVertexAttributesFeaturesEXT>();
|
device_chain.unlink<vk::PhysicalDeviceLegacyVertexAttributesFeaturesEXT>();
|
||||||
}
|
}
|
||||||
|
if (!provoking_vertex) {
|
||||||
|
device_chain.unlink<vk::PhysicalDeviceProvokingVertexFeaturesEXT>();
|
||||||
|
}
|
||||||
if (!shader_atomic_float2) {
|
if (!shader_atomic_float2) {
|
||||||
device_chain.unlink<vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT>();
|
device_chain.unlink<vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT>();
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,16 @@ public:
|
|||||||
return depth_clip_control;
|
return depth_clip_control;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true when VK_EXT_depth_clip_enable is supported
|
||||||
|
bool IsDepthClipEnableSupported() const {
|
||||||
|
return depth_clip_enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true when VK_EXT_depth_clamp_control is supported
|
||||||
|
bool IsDepthClampControlSupported() const {
|
||||||
|
return depth_clamp_control;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true when VK_EXT_depth_range_unrestricted is supported
|
/// Returns true when VK_EXT_depth_range_unrestricted is supported
|
||||||
bool IsDepthRangeUnrestrictedSupported() const {
|
bool IsDepthRangeUnrestrictedSupported() const {
|
||||||
return depth_range_unrestricted;
|
return depth_range_unrestricted;
|
||||||
@ -150,6 +160,11 @@ public:
|
|||||||
return legacy_vertex_attributes;
|
return legacy_vertex_attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true when VK_EXT_provoking_vertex is supported.
|
||||||
|
bool IsProvokingVertexSupported() const {
|
||||||
|
return provoking_vertex;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true when VK_AMD_shader_image_load_store_lod is supported.
|
/// Returns true when VK_AMD_shader_image_load_store_lod is supported.
|
||||||
bool IsImageLoadStoreLodSupported() const {
|
bool IsImageLoadStoreLodSupported() const {
|
||||||
return image_load_store_lod;
|
return image_load_store_lod;
|
||||||
@ -351,6 +366,11 @@ public:
|
|||||||
return driver_id != vk::DriverId::eMoltenvk;
|
return driver_id != vk::DriverId::eMoltenvk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if logic ops are supported by the device.
|
||||||
|
bool IsLogicOpSupported() const {
|
||||||
|
return features.logicOp;
|
||||||
|
}
|
||||||
|
|
||||||
/// Determines if a format is supported for a set of feature flags.
|
/// Determines if a format is supported for a set of feature flags.
|
||||||
[[nodiscard]] bool IsFormatSupported(vk::Format format, vk::FormatFeatureFlags2 flags) const;
|
[[nodiscard]] bool IsFormatSupported(vk::Format format, vk::FormatFeatureFlags2 flags) const;
|
||||||
|
|
||||||
@ -399,12 +419,15 @@ private:
|
|||||||
bool custom_border_color{};
|
bool custom_border_color{};
|
||||||
bool fragment_shader_barycentric{};
|
bool fragment_shader_barycentric{};
|
||||||
bool depth_clip_control{};
|
bool depth_clip_control{};
|
||||||
|
bool depth_clip_enable{};
|
||||||
|
bool depth_clamp_control{};
|
||||||
bool depth_range_unrestricted{};
|
bool depth_range_unrestricted{};
|
||||||
bool dynamic_state_3{};
|
bool dynamic_state_3{};
|
||||||
bool vertex_input_dynamic_state{};
|
bool vertex_input_dynamic_state{};
|
||||||
bool robustness2{};
|
bool robustness2{};
|
||||||
bool list_restart{};
|
bool list_restart{};
|
||||||
bool legacy_vertex_attributes{};
|
bool legacy_vertex_attributes{};
|
||||||
|
bool provoking_vertex{};
|
||||||
bool shader_stencil_export{};
|
bool shader_stencil_export{};
|
||||||
bool image_load_store_lod{};
|
bool image_load_store_lod{};
|
||||||
bool amd_gcn_shader{};
|
bool amd_gcn_shader{};
|
||||||
|
@ -285,26 +285,21 @@ bool PipelineCache::RefreshGraphicsKey() {
|
|||||||
auto& regs = liverpool->regs;
|
auto& regs = liverpool->regs;
|
||||||
auto& key = graphics_key;
|
auto& key = graphics_key;
|
||||||
|
|
||||||
const auto depth_format = instance.GetSupportedFormat(
|
key.z_format = regs.depth_buffer.DepthValid() ? regs.depth_buffer.z_info.format.Value()
|
||||||
LiverpoolToVK::DepthFormat(regs.depth_buffer.z_info.format,
|
: Liverpool::DepthBuffer::ZFormat::Invalid;
|
||||||
regs.depth_buffer.stencil_info.format),
|
key.stencil_format = regs.depth_buffer.StencilValid()
|
||||||
vk::FormatFeatureFlagBits2::eDepthStencilAttachment);
|
? regs.depth_buffer.stencil_info.format.Value()
|
||||||
if (regs.depth_buffer.DepthValid()) {
|
: Liverpool::DepthBuffer::StencilFormat::Invalid;
|
||||||
key.depth_format = depth_format;
|
key.depth_clip_enable = regs.clipper_control.ZclipEnable();
|
||||||
} else {
|
key.clip_space = regs.clipper_control.clip_space;
|
||||||
key.depth_format = vk::Format::eUndefined;
|
key.provoking_vtx_last = regs.polygon_control.provoking_vtx_last;
|
||||||
}
|
|
||||||
if (regs.depth_buffer.StencilValid()) {
|
|
||||||
key.stencil_format = depth_format;
|
|
||||||
} else {
|
|
||||||
key.stencil_format = vk::Format::eUndefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
key.prim_type = regs.primitive_type;
|
key.prim_type = regs.primitive_type;
|
||||||
key.polygon_mode = regs.polygon_control.PolyMode();
|
key.polygon_mode = regs.polygon_control.PolyMode();
|
||||||
key.clip_space = regs.clipper_control.clip_space;
|
key.logic_op = regs.color_control.rop3;
|
||||||
key.num_samples = regs.NumSamples();
|
key.num_samples = regs.NumSamples();
|
||||||
|
|
||||||
|
RefreshDepthClampRange();
|
||||||
|
|
||||||
const bool skip_cb_binding =
|
const bool skip_cb_binding =
|
||||||
regs.color_control.mode == AmdGpu::Liverpool::ColorControl::OperationMode::Disable;
|
regs.color_control.mode == AmdGpu::Liverpool::ColorControl::OperationMode::Disable;
|
||||||
|
|
||||||
@ -491,7 +486,63 @@ bool PipelineCache::RefreshGraphicsKey() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} // namespace Vulkan
|
}
|
||||||
|
|
||||||
|
void PipelineCache::RefreshDepthClampRange() {
|
||||||
|
auto& regs = liverpool->regs;
|
||||||
|
auto& key = graphics_key;
|
||||||
|
|
||||||
|
key.depth_clamp_enable = !regs.depth_render_override.disable_viewport_clamp;
|
||||||
|
if (key.z_format == Liverpool::DepthBuffer::ZFormat::Invalid || !key.depth_clamp_enable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool depth_clamp_can_use_viewport_range = true;
|
||||||
|
bool depth_clamp_is_same_on_all_viewports = true;
|
||||||
|
float zmin = std::numeric_limits<float>::max();
|
||||||
|
float zmax = std::numeric_limits<float>::max();
|
||||||
|
const auto& vp_ctl = regs.viewport_control;
|
||||||
|
for (u32 i = 0; i < Liverpool::NumViewports; i++) {
|
||||||
|
const auto& vp = regs.viewports[i];
|
||||||
|
const auto& vp_d = regs.viewport_depths[i];
|
||||||
|
if (vp.xscale == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto zoffset = vp_ctl.zoffset_enable ? vp.zoffset : 0.f;
|
||||||
|
const auto zscale = vp_ctl.zscale_enable ? vp.zscale : 1.f;
|
||||||
|
|
||||||
|
float min_depth;
|
||||||
|
float max_depth;
|
||||||
|
if (regs.clipper_control.clip_space == AmdGpu::Liverpool::ClipSpace::MinusWToW) {
|
||||||
|
min_depth = zoffset - zscale;
|
||||||
|
max_depth = zoffset + zscale;
|
||||||
|
} else {
|
||||||
|
min_depth = zoffset;
|
||||||
|
max_depth = zoffset + zscale;
|
||||||
|
}
|
||||||
|
if (zmin == std::numeric_limits<float>::max()) {
|
||||||
|
zmin = vp_d.zmin;
|
||||||
|
zmax = vp_d.zmax;
|
||||||
|
}
|
||||||
|
depth_clamp_is_same_on_all_viewports &= (zmin == vp_d.zmin && zmax == vp_d.zmax);
|
||||||
|
depth_clamp_can_use_viewport_range &= (min_depth == vp_d.zmin && max_depth == vp_d.zmax);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zmin == std::numeric_limits<float>::max()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!depth_clamp_can_use_viewport_range && !depth_clamp_is_same_on_all_viewports) {
|
||||||
|
LOG_ERROR(Render_Vulkan,
|
||||||
|
"Viewport depth clamping configuration cannot be accurately emulated");
|
||||||
|
}
|
||||||
|
|
||||||
|
key.depth_clamp_user_defined_range = !depth_clamp_can_use_viewport_range;
|
||||||
|
if (key.depth_clamp_user_defined_range) {
|
||||||
|
key.min_depth_clamp = zmin;
|
||||||
|
key.max_depth_clamp = zmax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool PipelineCache::RefreshComputeKey() {
|
bool PipelineCache::RefreshComputeKey() {
|
||||||
Shader::Backend::Bindings binding{};
|
Shader::Backend::Bindings binding{};
|
||||||
|
@ -76,6 +76,8 @@ private:
|
|||||||
bool RefreshGraphicsKey();
|
bool RefreshGraphicsKey();
|
||||||
bool RefreshComputeKey();
|
bool RefreshComputeKey();
|
||||||
|
|
||||||
|
void RefreshDepthClampRange();
|
||||||
|
|
||||||
void DumpShader(std::span<const u32> code, u64 hash, Shader::Stage stage, size_t perm_idx,
|
void DumpShader(std::span<const u32> code, u64 hash, Shader::Stage stage, size_t perm_idx,
|
||||||
std::string_view ext);
|
std::string_view ext);
|
||||||
std::optional<std::vector<u32>> GetShaderPatch(u64 hash, Shader::Stage stage, size_t perm_idx,
|
std::optional<std::vector<u32>> GetShaderPatch(u64 hash, Shader::Stage stage, size_t perm_idx,
|
||||||
|
@ -1014,9 +1014,10 @@ void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) const {
|
|||||||
UpdateViewportScissorState();
|
UpdateViewportScissorState();
|
||||||
UpdateDepthStencilState();
|
UpdateDepthStencilState();
|
||||||
UpdatePrimitiveState();
|
UpdatePrimitiveState();
|
||||||
|
UpdateRasterizationState();
|
||||||
|
|
||||||
auto& dynamic_state = scheduler.GetDynamicState();
|
auto& dynamic_state = scheduler.GetDynamicState();
|
||||||
dynamic_state.SetBlendConstants(&liverpool->regs.blend_constants.red);
|
dynamic_state.SetBlendConstants(liverpool->regs.blend_constants);
|
||||||
dynamic_state.SetColorWriteMasks(pipeline.GetWriteMasks());
|
dynamic_state.SetColorWriteMasks(pipeline.GetWriteMasks());
|
||||||
|
|
||||||
// Commit new dynamic state to the command buffer.
|
// Commit new dynamic state to the command buffer.
|
||||||
@ -1086,12 +1087,6 @@ void Rasterizer::UpdateViewportScissorState() const {
|
|||||||
viewport.maxDepth = zoffset + zscale;
|
viewport.maxDepth = zoffset + zscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!regs.depth_render_override.disable_viewport_clamp) {
|
|
||||||
// Apply depth clamp.
|
|
||||||
viewport.minDepth = std::max(viewport.minDepth, vp_d.zmin);
|
|
||||||
viewport.maxDepth = std::min(viewport.maxDepth, vp_d.zmax);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!instance.IsDepthRangeUnrestrictedSupported()) {
|
if (!instance.IsDepthRangeUnrestrictedSupported()) {
|
||||||
// Unrestricted depth range not supported by device. Restrict to valid range.
|
// Unrestricted depth range not supported by device. Restrict to valid range.
|
||||||
viewport.minDepth = std::max(viewport.minDepth, 0.f);
|
viewport.minDepth = std::max(viewport.minDepth, 0.f);
|
||||||
@ -1231,10 +1226,17 @@ void Rasterizer::UpdatePrimitiveState() const {
|
|||||||
const auto front_face = LiverpoolToVK::FrontFace(regs.polygon_control.front_face);
|
const auto front_face = LiverpoolToVK::FrontFace(regs.polygon_control.front_face);
|
||||||
|
|
||||||
dynamic_state.SetPrimitiveRestartEnabled(prim_restart);
|
dynamic_state.SetPrimitiveRestartEnabled(prim_restart);
|
||||||
|
dynamic_state.SetRasterizerDiscardEnabled(regs.clipper_control.dx_rasterization_kill);
|
||||||
dynamic_state.SetCullMode(cull_mode);
|
dynamic_state.SetCullMode(cull_mode);
|
||||||
dynamic_state.SetFrontFace(front_face);
|
dynamic_state.SetFrontFace(front_face);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Rasterizer::UpdateRasterizationState() const {
|
||||||
|
const auto& regs = liverpool->regs;
|
||||||
|
auto& dynamic_state = scheduler.GetDynamicState();
|
||||||
|
dynamic_state.SetLineWidth(regs.line_control.Width());
|
||||||
|
}
|
||||||
|
|
||||||
void Rasterizer::ScopeMarkerBegin(const std::string_view& str, bool from_guest) {
|
void Rasterizer::ScopeMarkerBegin(const std::string_view& str, bool from_guest) {
|
||||||
if ((from_guest && !Config::getVkGuestMarkersEnabled()) ||
|
if ((from_guest && !Config::getVkGuestMarkersEnabled()) ||
|
||||||
(!from_guest && !Config::getVkHostMarkersEnabled())) {
|
(!from_guest && !Config::getVkHostMarkersEnabled())) {
|
||||||
|
@ -94,6 +94,7 @@ private:
|
|||||||
void UpdateViewportScissorState() const;
|
void UpdateViewportScissorState() const;
|
||||||
void UpdateDepthStencilState() const;
|
void UpdateDepthStencilState() const;
|
||||||
void UpdatePrimitiveState() const;
|
void UpdatePrimitiveState() const;
|
||||||
|
void UpdateRasterizationState() const;
|
||||||
|
|
||||||
bool FilterDraw();
|
bool FilterDraw();
|
||||||
|
|
||||||
|
@ -308,6 +308,10 @@ void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmd
|
|||||||
cmdbuf.setPrimitiveRestartEnable(primitive_restart_enable);
|
cmdbuf.setPrimitiveRestartEnable(primitive_restart_enable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (dirty_state.rasterizer_discard_enable) {
|
||||||
|
dirty_state.rasterizer_discard_enable = false;
|
||||||
|
cmdbuf.setRasterizerDiscardEnable(rasterizer_discard_enable);
|
||||||
|
}
|
||||||
if (dirty_state.cull_mode) {
|
if (dirty_state.cull_mode) {
|
||||||
dirty_state.cull_mode = false;
|
dirty_state.cull_mode = false;
|
||||||
cmdbuf.setCullMode(cull_mode);
|
cmdbuf.setCullMode(cull_mode);
|
||||||
@ -318,7 +322,7 @@ void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmd
|
|||||||
}
|
}
|
||||||
if (dirty_state.blend_constants) {
|
if (dirty_state.blend_constants) {
|
||||||
dirty_state.blend_constants = false;
|
dirty_state.blend_constants = false;
|
||||||
cmdbuf.setBlendConstants(blend_constants);
|
cmdbuf.setBlendConstants(blend_constants.data());
|
||||||
}
|
}
|
||||||
if (dirty_state.color_write_masks) {
|
if (dirty_state.color_write_masks) {
|
||||||
dirty_state.color_write_masks = false;
|
dirty_state.color_write_masks = false;
|
||||||
@ -326,6 +330,10 @@ void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmd
|
|||||||
cmdbuf.setColorWriteMaskEXT(0, color_write_masks);
|
cmdbuf.setColorWriteMaskEXT(0, color_write_masks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (dirty_state.line_width) {
|
||||||
|
dirty_state.line_width = false;
|
||||||
|
cmdbuf.setLineWidth(line_width);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
@ -96,11 +96,13 @@ struct DynamicState {
|
|||||||
bool stencil_back_compare_mask : 1;
|
bool stencil_back_compare_mask : 1;
|
||||||
|
|
||||||
bool primitive_restart_enable : 1;
|
bool primitive_restart_enable : 1;
|
||||||
|
bool rasterizer_discard_enable : 1;
|
||||||
bool cull_mode : 1;
|
bool cull_mode : 1;
|
||||||
bool front_face : 1;
|
bool front_face : 1;
|
||||||
|
|
||||||
bool blend_constants : 1;
|
bool blend_constants : 1;
|
||||||
bool color_write_masks : 1;
|
bool color_write_masks : 1;
|
||||||
|
bool line_width : 1;
|
||||||
} dirty_state{};
|
} dirty_state{};
|
||||||
|
|
||||||
Viewports viewports{};
|
Viewports viewports{};
|
||||||
@ -130,11 +132,13 @@ struct DynamicState {
|
|||||||
u32 stencil_back_compare_mask{};
|
u32 stencil_back_compare_mask{};
|
||||||
|
|
||||||
bool primitive_restart_enable{};
|
bool primitive_restart_enable{};
|
||||||
|
bool rasterizer_discard_enable{};
|
||||||
vk::CullModeFlags cull_mode{};
|
vk::CullModeFlags cull_mode{};
|
||||||
vk::FrontFace front_face{};
|
vk::FrontFace front_face{};
|
||||||
|
|
||||||
float blend_constants[4]{};
|
std::array<float, 4> blend_constants{};
|
||||||
ColorWriteMasks color_write_masks{};
|
ColorWriteMasks color_write_masks{};
|
||||||
|
float line_width{};
|
||||||
|
|
||||||
/// Commits the dynamic state to the provided command buffer.
|
/// Commits the dynamic state to the provided command buffer.
|
||||||
void Commit(const Instance& instance, const vk::CommandBuffer& cmdbuf);
|
void Commit(const Instance& instance, const vk::CommandBuffer& cmdbuf);
|
||||||
@ -283,19 +287,33 @@ struct DynamicState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetBlendConstants(const float blend_constants_[4]) {
|
void SetBlendConstants(const std::array<float, 4> blend_constants_) {
|
||||||
if (!std::equal(blend_constants, std::end(blend_constants), blend_constants_)) {
|
if (blend_constants != blend_constants_) {
|
||||||
std::memcpy(blend_constants, blend_constants_, sizeof(blend_constants));
|
blend_constants = blend_constants_;
|
||||||
dirty_state.blend_constants = true;
|
dirty_state.blend_constants = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetRasterizerDiscardEnabled(const bool enabled) {
|
||||||
|
if (rasterizer_discard_enable != enabled) {
|
||||||
|
rasterizer_discard_enable = enabled;
|
||||||
|
dirty_state.rasterizer_discard_enable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SetColorWriteMasks(const ColorWriteMasks& color_write_masks_) {
|
void SetColorWriteMasks(const ColorWriteMasks& color_write_masks_) {
|
||||||
if (!std::ranges::equal(color_write_masks, color_write_masks_)) {
|
if (!std::ranges::equal(color_write_masks, color_write_masks_)) {
|
||||||
color_write_masks = color_write_masks_;
|
color_write_masks = color_write_masks_;
|
||||||
dirty_state.color_write_masks = true;
|
dirty_state.color_write_masks = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetLineWidth(const float width) {
|
||||||
|
if (line_width != width) {
|
||||||
|
line_width = width;
|
||||||
|
dirty_state.line_width = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Scheduler {
|
class Scheduler {
|
||||||
|
Loading…
Reference in New Issue
Block a user