diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Formats.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Formats.cpp index a50995113d..cd26a1ec96 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Formats.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Formats.cpp @@ -128,8 +128,6 @@ D3D12_COMPARISON_FUNC get_compare_func(u32 op) case CELL_GCM_NOTEQUAL: return D3D12_COMPARISON_FUNC_NOT_EQUAL; case CELL_GCM_GEQUAL: return D3D12_COMPARISON_FUNC_GREATER_EQUAL; case CELL_GCM_ALWAYS: return D3D12_COMPARISON_FUNC_ALWAYS; - case CELL_GCM_ZERO: - break; } throw EXCEPTION("Invalid or unsupported compare func (0x%x)", op); } diff --git a/rpcs3/Emu/RSX/VK/VKFormats.h b/rpcs3/Emu/RSX/VK/VKFormats.h index e970166e3f..9765d826de 100644 --- a/rpcs3/Emu/RSX/VK/VKFormats.h +++ b/rpcs3/Emu/RSX/VK/VKFormats.h @@ -12,6 +12,8 @@ namespace vk gpu_formats_support get_optimal_tiling_supported_formats(VkPhysicalDevice physical_device); VkFormat get_compatible_depth_surface_format(const gpu_formats_support &support, rsx::surface_depth_format format); + VkStencilOp get_stencil_op(u32 op); + VkLogicOp get_logic_op(u32 op); std::tuple get_min_filter_and_mip(rsx::texture_minify_filter min_filter); VkFilter get_mag_filter(rsx::texture_magnify_filter mag_filter); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 16c4c99542..c195c9acd1 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -181,6 +181,30 @@ namespace vk } } + VkLogicOp get_logic_op(u32 op) + { + switch (op) + { + case CELL_GCM_CLEAR: return VK_LOGIC_OP_CLEAR; + case CELL_GCM_AND: return VK_LOGIC_OP_AND; + case CELL_GCM_AND_REVERSE: return VK_LOGIC_OP_AND_REVERSE; + case CELL_GCM_COPY: return VK_LOGIC_OP_COPY; + case CELL_GCM_AND_INVERTED: return VK_LOGIC_OP_AND_INVERTED; + case CELL_GCM_NOOP: return VK_LOGIC_OP_NO_OP; + case CELL_GCM_XOR: return VK_LOGIC_OP_XOR; + case CELL_GCM_OR: return VK_LOGIC_OP_OR; + case CELL_GCM_NOR: return VK_LOGIC_OP_NOR; + case CELL_GCM_EQUIV: return VK_LOGIC_OP_EQUIVALENT; + case CELL_GCM_INVERT: return VK_LOGIC_OP_INVERT; + case CELL_GCM_OR_REVERSE: return VK_LOGIC_OP_OR_REVERSE; + case CELL_GCM_COPY_INVERTED: return VK_LOGIC_OP_COPY_INVERTED; + case CELL_GCM_OR_INVERTED: return VK_LOGIC_OP_OR_INVERTED; + case CELL_GCM_NAND: return VK_LOGIC_OP_NAND; + default: + throw EXCEPTION("Unknown logic op 0x%X", op); + } + } + VkBlendFactor get_blend_factor(u16 factor) { switch (factor) @@ -217,6 +241,23 @@ namespace vk throw EXCEPTION("Unknown blend op: 0x%X", op); } } + + VkStencilOp get_stencil_op(u32 op) + { + switch (op) + { + case CELL_GCM_KEEP: return VK_STENCIL_OP_KEEP; + case CELL_GCM_ZERO: return VK_STENCIL_OP_ZERO; + case CELL_GCM_REPLACE: return VK_STENCIL_OP_REPLACE; + case CELL_GCM_INCR: return VK_STENCIL_OP_INCREMENT_AND_CLAMP; + case CELL_GCM_DECR: return VK_STENCIL_OP_DECREMENT_AND_CLAMP; + case CELL_GCM_INVERT: return VK_STENCIL_OP_INVERT; + case CELL_GCM_INCR_WRAP: return VK_STENCIL_OP_INCREMENT_AND_WRAP; + case CELL_GCM_DECR_WRAP: return VK_STENCIL_OP_DECREMENT_AND_WRAP; + default: + throw EXCEPTION("Unknown stencil op: 0x%X", op); + } + } } @@ -886,17 +927,48 @@ bool VKGSRender::load_program() } } - + if (rsx::method_registers[NV4097_SET_LOGIC_OP_ENABLE]) + { + properties.cs.logicOpEnable = true; + properties.cs.logicOp = vk::get_logic_op(rsx::method_registers[NV4097_SET_LOGIC_OP]); + } properties.ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; properties.ds.depthWriteEnable = (!!rsx::method_registers[NV4097_SET_DEPTH_MASK]) ? VK_TRUE : VK_FALSE; - properties.ds.depthBoundsTestEnable = VK_FALSE; - properties.ds.back.failOp = VK_STENCIL_OP_KEEP; - properties.ds.back.passOp = VK_STENCIL_OP_KEEP; - properties.ds.back.compareOp = VK_COMPARE_OP_ALWAYS; - properties.ds.stencilTestEnable = VK_FALSE; - properties.ds.front = properties.ds.back; + if (rsx::method_registers[NV4097_SET_DEPTH_BOUNDS_TEST_ENABLE]) + { + properties.ds.depthBoundsTestEnable = VK_TRUE; + properties.ds.minDepthBounds = (f32&)rsx::method_registers[NV4097_SET_DEPTH_BOUNDS_MIN]; + properties.ds.maxDepthBounds = (f32&)rsx::method_registers[NV4097_SET_DEPTH_BOUNDS_MAX]; + } + else + properties.ds.depthBoundsTestEnable = VK_FALSE; + + if (rsx::method_registers[NV4097_SET_STENCIL_TEST_ENABLE]) + { + properties.ds.stencilTestEnable = VK_TRUE; + properties.ds.front.writeMask = rsx::method_registers[NV4097_SET_STENCIL_MASK]; + properties.ds.front.compareMask = rsx::method_registers[NV4097_SET_STENCIL_FUNC_MASK]; + properties.ds.front.reference = rsx::method_registers[NV4097_SET_STENCIL_FUNC_REF]; + properties.ds.front.failOp = vk::get_stencil_op(rsx::method_registers[NV4097_SET_STENCIL_OP_FAIL]); + properties.ds.front.passOp = vk::get_stencil_op(rsx::method_registers[NV4097_SET_STENCIL_OP_ZPASS]); + properties.ds.front.depthFailOp = vk::get_stencil_op(rsx::method_registers[NV4097_SET_STENCIL_OP_ZFAIL]); + properties.ds.front.compareOp = vk::compare_op(rsx::method_registers[NV4097_SET_STENCIL_FUNC]); + + if (rsx::method_registers[NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE]) + { + properties.ds.back.failOp = vk::get_stencil_op(rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_FAIL]); + properties.ds.back.passOp = vk::get_stencil_op(rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_ZPASS]); + properties.ds.back.depthFailOp = vk::get_stencil_op(rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_ZFAIL]); + properties.ds.back.compareOp = vk::compare_op(rsx::method_registers[NV4097_SET_BACK_STENCIL_FUNC]); + } + else + properties.ds.back = properties.ds.front; + } + else + properties.ds.stencilTestEnable = VK_FALSE; + if (!!rsx::method_registers[NV4097_SET_DEPTH_TEST_ENABLE]) { properties.ds.depthTestEnable = VK_TRUE; diff --git a/rpcs3/Emu/RSX/VK/VKProgramBuffer.h b/rpcs3/Emu/RSX/VK/VKProgramBuffer.h index 68f7128b29..642f39f1fb 100644 --- a/rpcs3/Emu/RSX/VK/VKProgramBuffer.h +++ b/rpcs3/Emu/RSX/VK/VKProgramBuffer.h @@ -11,6 +11,8 @@ namespace vk VkPipelineInputAssemblyStateCreateInfo ia; VkPipelineDepthStencilStateCreateInfo ds; VkPipelineColorBlendAttachmentState att_state[4]; + VkPipelineColorBlendStateCreateInfo cs; + VkRenderPass render_pass; int num_targets;