mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-01-15 11:25:13 +00:00
renderer_vulkan: Make sure at least one viewport is set (#1859)
This commit is contained in:
parent
db43c601fc
commit
3c111202e1
|
@ -133,37 +133,23 @@ GraphicsPipeline::GraphicsPipeline(
|
||||||
.sampleShadingEnable = false,
|
.sampleShadingEnable = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::Viewport viewport = {
|
|
||||||
.x = 0.0f,
|
|
||||||
.y = 0.0f,
|
|
||||||
.width = 1.0f,
|
|
||||||
.height = 1.0f,
|
|
||||||
.minDepth = 0.0f,
|
|
||||||
.maxDepth = 1.0f,
|
|
||||||
};
|
|
||||||
|
|
||||||
const vk::Rect2D scissor = {
|
|
||||||
.offset = {0, 0},
|
|
||||||
.extent = {1, 1},
|
|
||||||
};
|
|
||||||
|
|
||||||
const vk::PipelineViewportDepthClipControlCreateInfoEXT clip_control = {
|
const vk::PipelineViewportDepthClipControlCreateInfoEXT clip_control = {
|
||||||
.negativeOneToOne = key.clip_space == Liverpool::ClipSpace::MinusWToW,
|
.negativeOneToOne = key.clip_space == Liverpool::ClipSpace::MinusWToW,
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::PipelineViewportStateCreateInfo viewport_info = {
|
const vk::PipelineViewportStateCreateInfo viewport_info = {
|
||||||
.pNext = instance.IsDepthClipControlSupported() ? &clip_control : nullptr,
|
.pNext = instance.IsDepthClipControlSupported() ? &clip_control : nullptr,
|
||||||
.viewportCount = 1,
|
|
||||||
.pViewports = &viewport,
|
|
||||||
.scissorCount = 1,
|
|
||||||
.pScissors = &scissor,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::container::static_vector<vk::DynamicState, 14> dynamic_states = {
|
boost::container::static_vector<vk::DynamicState, 14> dynamic_states = {
|
||||||
vk::DynamicState::eViewport, vk::DynamicState::eScissor,
|
vk::DynamicState::eViewportWithCountEXT,
|
||||||
vk::DynamicState::eBlendConstants, vk::DynamicState::eDepthBounds,
|
vk::DynamicState::eScissorWithCountEXT,
|
||||||
vk::DynamicState::eDepthBias, vk::DynamicState::eStencilReference,
|
vk::DynamicState::eBlendConstants,
|
||||||
vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask,
|
vk::DynamicState::eDepthBounds,
|
||||||
|
vk::DynamicState::eDepthBias,
|
||||||
|
vk::DynamicState::eStencilReference,
|
||||||
|
vk::DynamicState::eStencilCompareMask,
|
||||||
|
vk::DynamicState::eStencilWriteMask,
|
||||||
vk::DynamicState::eStencilOpEXT,
|
vk::DynamicState::eStencilOpEXT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1019,17 +1019,44 @@ void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rasterizer::UpdateViewportScissorState() {
|
void Rasterizer::UpdateViewportScissorState() {
|
||||||
auto& regs = liverpool->regs;
|
const auto& regs = liverpool->regs;
|
||||||
|
|
||||||
|
const auto combined_scissor_value_tl = [](s16 scr, s16 win, s16 gen, s16 win_offset) {
|
||||||
|
return std::max({scr, s16(win + win_offset), s16(gen + win_offset)});
|
||||||
|
};
|
||||||
|
const auto combined_scissor_value_br = [](s16 scr, s16 win, s16 gen, s16 win_offset) {
|
||||||
|
return std::min({scr, s16(win + win_offset), s16(gen + win_offset)});
|
||||||
|
};
|
||||||
|
const bool enable_offset = !regs.window_scissor.window_offset_disable.Value();
|
||||||
|
|
||||||
|
Liverpool::Scissor scsr{};
|
||||||
|
scsr.top_left_x = combined_scissor_value_tl(
|
||||||
|
regs.screen_scissor.top_left_x, s16(regs.window_scissor.top_left_x.Value()),
|
||||||
|
s16(regs.generic_scissor.top_left_x.Value()),
|
||||||
|
enable_offset ? regs.window_offset.window_x_offset : 0);
|
||||||
|
scsr.top_left_y = combined_scissor_value_tl(
|
||||||
|
regs.screen_scissor.top_left_y, s16(regs.window_scissor.top_left_y.Value()),
|
||||||
|
s16(regs.generic_scissor.top_left_y.Value()),
|
||||||
|
enable_offset ? regs.window_offset.window_y_offset : 0);
|
||||||
|
scsr.bottom_right_x = combined_scissor_value_br(
|
||||||
|
regs.screen_scissor.bottom_right_x, regs.window_scissor.bottom_right_x,
|
||||||
|
regs.generic_scissor.bottom_right_x,
|
||||||
|
enable_offset ? regs.window_offset.window_x_offset : 0);
|
||||||
|
scsr.bottom_right_y = combined_scissor_value_br(
|
||||||
|
regs.screen_scissor.bottom_right_y, regs.window_scissor.bottom_right_y,
|
||||||
|
regs.generic_scissor.bottom_right_y,
|
||||||
|
enable_offset ? regs.window_offset.window_y_offset : 0);
|
||||||
|
|
||||||
boost::container::static_vector<vk::Viewport, Liverpool::NumViewports> viewports;
|
boost::container::static_vector<vk::Viewport, Liverpool::NumViewports> viewports;
|
||||||
boost::container::static_vector<vk::Rect2D, Liverpool::NumViewports> scissors;
|
boost::container::static_vector<vk::Rect2D, Liverpool::NumViewports> scissors;
|
||||||
|
|
||||||
|
const auto& vp_ctl = regs.viewport_control;
|
||||||
const float reduce_z =
|
const float reduce_z =
|
||||||
instance.IsDepthClipControlSupported() &&
|
instance.IsDepthClipControlSupported() &&
|
||||||
regs.clipper_control.clip_space == AmdGpu::Liverpool::ClipSpace::MinusWToW
|
regs.clipper_control.clip_space == AmdGpu::Liverpool::ClipSpace::MinusWToW
|
||||||
? 1.0f
|
? 1.0f
|
||||||
: 0.0f;
|
: 0.0f;
|
||||||
const auto vp_ctl = regs.viewport_control;
|
|
||||||
for (u32 i = 0; i < Liverpool::NumViewports; i++) {
|
for (u32 i = 0; i < Liverpool::NumViewports; i++) {
|
||||||
const auto& vp = regs.viewports[i];
|
const auto& vp = regs.viewports[i];
|
||||||
const auto& vp_d = regs.viewport_depths[i];
|
const auto& vp_d = regs.viewport_depths[i];
|
||||||
|
@ -1050,53 +1077,17 @@ void Rasterizer::UpdateViewportScissorState() {
|
||||||
.minDepth = zoffset - zscale * reduce_z,
|
.minDepth = zoffset - zscale * reduce_z,
|
||||||
.maxDepth = zscale + zoffset,
|
.maxDepth = zscale + zoffset,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
const bool enable_offset = !regs.window_scissor.window_offset_disable.Value();
|
|
||||||
Liverpool::Scissor scsr{};
|
|
||||||
const auto combined_scissor_value_tl = [](s16 scr, s16 win, s16 gen, s16 win_offset) {
|
|
||||||
return std::max({scr, s16(win + win_offset), s16(gen + win_offset)});
|
|
||||||
};
|
|
||||||
|
|
||||||
scsr.top_left_x = combined_scissor_value_tl(
|
|
||||||
regs.screen_scissor.top_left_x, s16(regs.window_scissor.top_left_x.Value()),
|
|
||||||
s16(regs.generic_scissor.top_left_x.Value()),
|
|
||||||
enable_offset ? regs.window_offset.window_x_offset : 0);
|
|
||||||
|
|
||||||
scsr.top_left_y = combined_scissor_value_tl(
|
|
||||||
regs.screen_scissor.top_left_y, s16(regs.window_scissor.top_left_y.Value()),
|
|
||||||
s16(regs.generic_scissor.top_left_y.Value()),
|
|
||||||
enable_offset ? regs.window_offset.window_y_offset : 0);
|
|
||||||
|
|
||||||
const auto combined_scissor_value_br = [](s16 scr, s16 win, s16 gen, s16 win_offset) {
|
|
||||||
return std::min({scr, s16(win + win_offset), s16(gen + win_offset)});
|
|
||||||
};
|
|
||||||
|
|
||||||
scsr.bottom_right_x = combined_scissor_value_br(
|
|
||||||
regs.screen_scissor.bottom_right_x, regs.window_scissor.bottom_right_x,
|
|
||||||
regs.generic_scissor.bottom_right_x,
|
|
||||||
enable_offset ? regs.window_offset.window_x_offset : 0);
|
|
||||||
|
|
||||||
scsr.bottom_right_y = combined_scissor_value_br(
|
|
||||||
regs.screen_scissor.bottom_right_y, regs.window_scissor.bottom_right_y,
|
|
||||||
regs.generic_scissor.bottom_right_y,
|
|
||||||
enable_offset ? regs.window_offset.window_y_offset : 0);
|
|
||||||
|
|
||||||
for (u32 idx = 0; idx < Liverpool::NumViewports; idx++) {
|
|
||||||
if (regs.viewports[idx].xscale == 0) {
|
|
||||||
// Scissor and viewport counts should be equal.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto vp_scsr = scsr;
|
auto vp_scsr = scsr;
|
||||||
if (regs.mode_control.vport_scissor_enable) {
|
if (regs.mode_control.vport_scissor_enable) {
|
||||||
vp_scsr.top_left_x =
|
vp_scsr.top_left_x =
|
||||||
std::max(vp_scsr.top_left_x, s16(regs.viewport_scissors[idx].top_left_x.Value()));
|
std::max(vp_scsr.top_left_x, s16(regs.viewport_scissors[i].top_left_x.Value()));
|
||||||
vp_scsr.top_left_y =
|
vp_scsr.top_left_y =
|
||||||
std::max(vp_scsr.top_left_y, s16(regs.viewport_scissors[idx].top_left_y.Value()));
|
std::max(vp_scsr.top_left_y, s16(regs.viewport_scissors[i].top_left_y.Value()));
|
||||||
vp_scsr.bottom_right_x =
|
vp_scsr.bottom_right_x =
|
||||||
std::min(vp_scsr.bottom_right_x, regs.viewport_scissors[idx].bottom_right_x);
|
std::min(vp_scsr.bottom_right_x, regs.viewport_scissors[i].bottom_right_x);
|
||||||
vp_scsr.bottom_right_y =
|
vp_scsr.bottom_right_y =
|
||||||
std::min(vp_scsr.bottom_right_y, regs.viewport_scissors[idx].bottom_right_y);
|
std::min(vp_scsr.bottom_right_y, regs.viewport_scissors[i].bottom_right_y);
|
||||||
}
|
}
|
||||||
scissors.push_back({
|
scissors.push_back({
|
||||||
.offset = {vp_scsr.top_left_x, vp_scsr.top_left_y},
|
.offset = {vp_scsr.top_left_x, vp_scsr.top_left_y},
|
||||||
|
@ -1104,9 +1095,27 @@ void Rasterizer::UpdateViewportScissorState() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (viewports.empty()) {
|
||||||
|
// Vulkan requires providing at least one viewport.
|
||||||
|
constexpr vk::Viewport empty_viewport = {
|
||||||
|
.x = 0.0f,
|
||||||
|
.y = 0.0f,
|
||||||
|
.width = 1.0f,
|
||||||
|
.height = 1.0f,
|
||||||
|
.minDepth = 0.0f,
|
||||||
|
.maxDepth = 1.0f,
|
||||||
|
};
|
||||||
|
constexpr vk::Rect2D empty_scissor = {
|
||||||
|
.offset = {0, 0},
|
||||||
|
.extent = {1, 1},
|
||||||
|
};
|
||||||
|
viewports.push_back(empty_viewport);
|
||||||
|
scissors.push_back(empty_scissor);
|
||||||
|
}
|
||||||
|
|
||||||
const auto cmdbuf = scheduler.CommandBuffer();
|
const auto cmdbuf = scheduler.CommandBuffer();
|
||||||
cmdbuf.setViewport(0, viewports);
|
cmdbuf.setViewportWithCountEXT(viewports);
|
||||||
cmdbuf.setScissor(0, scissors);
|
cmdbuf.setScissorWithCountEXT(scissors);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rasterizer::ScopeMarkerBegin(const std::string_view& str) {
|
void Rasterizer::ScopeMarkerBegin(const std::string_view& str) {
|
||||||
|
|
Loading…
Reference in a new issue