account for max viewport limit, add todo for ViewportIndex

This commit is contained in:
Vladislav Mikhalin 2025-01-17 19:13:38 +03:00
parent b6f2ce34e0
commit 172308aab4
5 changed files with 33 additions and 14 deletions

View File

@ -47,14 +47,14 @@ void ConvertPositionToClipSpace(EmitContext& ctx) {
ctx.push_data_block, ctx.push_data_block,
ctx.ConstU32(PushData::YScaleIndex))}; ctx.ConstU32(PushData::YScaleIndex))};
const Id yscale{ctx.OpLoad(type, yscale_ptr)}; const Id yscale{ctx.OpLoad(type, yscale_ptr)};
Id ndc_x = ctx.OpFMul(type, x, xscale); const Id vport_w =
ndc_x = ctx.OpFAdd(type, ndc_x, xoffset); ctx.Constant(type, float(std::min<u32>(ctx.profile.max_viewport_width / 2, 8_KB)));
ndc_x = ctx.OpFDiv(type, ndc_x, ctx.Constant(type, float(8_KB))); const Id wnd_x = ctx.OpFAdd(type, ctx.OpFMul(type, x, xscale), xoffset);
ndc_x = ctx.OpFSub(type, ndc_x, ctx.Constant(type, 1.f)); const Id ndc_x = ctx.OpFSub(type, ctx.OpFDiv(type, wnd_x, vport_w), ctx.Constant(type, 1.f));
Id ndc_y = ctx.OpFMul(type, y, yscale); const Id vport_h =
ndc_y = ctx.OpFAdd(type, ndc_y, yoffset); ctx.Constant(type, float(std::min<u32>(ctx.profile.max_viewport_height / 2, 8_KB)));
ndc_y = ctx.OpFDiv(type, ndc_y, ctx.Constant(type, float(8_KB))); const Id wnd_y = ctx.OpFAdd(type, ctx.OpFMul(type, y, yscale), yoffset);
ndc_y = ctx.OpFSub(type, ndc_y, ctx.Constant(type, 1.f)); const Id ndc_y = ctx.OpFSub(type, ctx.OpFDiv(type, wnd_y, vport_h), ctx.Constant(type, 1.f));
const Id vector{ctx.OpCompositeConstruct(ctx.F32[4], std::array<Id, 4>({ndc_x, ndc_y, z, w}))}; const Id vector{ctx.OpCompositeConstruct(ctx.F32[4], std::array<Id, 4>({ndc_x, ndc_y, z, w}))};
ctx.OpStore(ctx.output_position, vector); ctx.OpStore(ctx.output_position, vector);
} }

View File

@ -30,6 +30,8 @@ struct Profile {
bool needs_manual_interpolation{}; bool needs_manual_interpolation{};
bool needs_lds_barriers{}; bool needs_lds_barriers{};
u64 min_ssbo_alignment{}; u64 min_ssbo_alignment{};
u32 max_viewport_width{};
u32 max_viewport_height{};
}; };
} // namespace Shader } // namespace Shader

View File

@ -274,6 +274,14 @@ public:
return min_imported_host_pointer_alignment; return min_imported_host_pointer_alignment;
} }
u32 GetMaxViewportWidth() const {
return properties.limits.maxViewportDimensions[0];
}
u32 GetMaxViewportHeight() const {
return properties.limits.maxViewportDimensions[1];
}
/// Returns the sample count flags supported by framebuffers. /// Returns the sample count flags supported by framebuffers.
vk::SampleCountFlags GetFramebufferSampleCounts() const { vk::SampleCountFlags GetFramebufferSampleCounts() const {
return properties.limits.framebufferColorSampleCounts & return properties.limits.framebufferColorSampleCounts &

View File

@ -210,6 +210,8 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_,
instance.GetDriverID() == vk::DriverId::eNvidiaProprietary, instance.GetDriverID() == vk::DriverId::eNvidiaProprietary,
.needs_lds_barriers = instance.GetDriverID() == vk::DriverId::eNvidiaProprietary || .needs_lds_barriers = instance.GetDriverID() == vk::DriverId::eNvidiaProprietary ||
instance.GetDriverID() == vk::DriverId::eMoltenvk, instance.GetDriverID() == vk::DriverId::eMoltenvk,
.max_viewport_width = instance.GetMaxViewportWidth(),
.max_viewport_height = instance.GetMaxViewportHeight(),
}; };
auto [cache_result, cache] = instance.GetDevice().createPipelineCacheUnique({}); auto [cache_result, cache] = instance.GetDevice().createPipelineCacheUnique({});
ASSERT_MSG(cache_result == vk::Result::eSuccess, "Failed to create pipeline cache: {}", ASSERT_MSG(cache_result == vk::Result::eSuccess, "Failed to create pipeline cache: {}",

View File

@ -504,10 +504,17 @@ bool Rasterizer::BindResources(const Pipeline* pipeline) {
} }
push_data.step0 = regs.vgt_instance_step_rate_0; push_data.step0 = regs.vgt_instance_step_rate_0;
push_data.step1 = regs.vgt_instance_step_rate_1; push_data.step1 = regs.vgt_instance_step_rate_1;
push_data.xoffset = regs.viewport_control.xoffset_enable ? regs.viewports[0].xoffset : 0.f;
push_data.xscale = regs.viewport_control.xscale_enable ? regs.viewports[0].xscale : 1.f; // TODO(roamic): add support for multiple viewports and geometry shaders when ViewportIndex
push_data.yoffset = regs.viewport_control.yoffset_enable ? regs.viewports[0].yoffset : 0.f; // is encountered and implemented in the recompiler.
push_data.yscale = regs.viewport_control.yscale_enable ? regs.viewports[0].yscale : 1.f; if (stage->stage == Shader::Stage::Vertex) {
push_data.xoffset =
regs.viewport_control.xoffset_enable ? regs.viewports[0].xoffset : 0.f;
push_data.xscale = regs.viewport_control.xscale_enable ? regs.viewports[0].xscale : 1.f;
push_data.yoffset =
regs.viewport_control.yoffset_enable ? regs.viewports[0].yoffset : 0.f;
push_data.yscale = regs.viewport_control.yscale_enable ? regs.viewports[0].yscale : 1.f;
}
stage->PushUd(binding, push_data); stage->PushUd(binding, push_data);
BindBuffers(*stage, binding, push_data, set_writes, buffer_barriers); BindBuffers(*stage, binding, push_data, set_writes, buffer_barriers);
@ -1174,8 +1181,8 @@ void Rasterizer::UpdateViewportScissorState(const GraphicsPipeline& pipeline) {
viewports.push_back({ viewports.push_back({
.x = 0.f, .x = 0.f,
.y = 0.f, .y = 0.f,
.width = float(16_KB), .width = float(std::min<u32>(instance.GetMaxViewportWidth(), 16_KB)),
.height = float(16_KB), .height = float(std::min<u32>(instance.GetMaxViewportHeight(), 16_KB)),
.minDepth = 0.0, .minDepth = 0.0,
.maxDepth = 1.0, .maxDepth = 1.0,
}); });