|
|
@ -45,12 +45,6 @@ |
|
|
|
|
|
|
|
|
namespace Vulkan { |
|
|
namespace Vulkan { |
|
|
|
|
|
|
|
|
using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
|
|
|
|
|
using MaxwellDrawState = Tegra::Engines::DrawManager::State; |
|
|
|
|
|
using VideoCommon::ImageViewId; |
|
|
|
|
|
using VideoCommon::ImageViewType; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace { |
|
|
namespace { |
|
|
struct DrawParams { |
|
|
struct DrawParams { |
|
|
u32 base_instance; |
|
|
u32 base_instance; |
|
|
@ -61,7 +55,7 @@ struct DrawParams { |
|
|
bool is_indexed; |
|
|
bool is_indexed; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t index, float scale) { |
|
|
|
|
|
|
|
|
VkViewport GetViewportState(const Device& device, const Tegra::Engines::Maxwell3D::Regs& regs, size_t index, float scale) { |
|
|
const auto& src = regs.viewport_transform[index]; |
|
|
const auto& src = regs.viewport_transform[index]; |
|
|
const auto conv = [scale](float value) { |
|
|
const auto conv = [scale](float value) { |
|
|
float new_value = value * scale; |
|
|
float new_value = value * scale; |
|
|
@ -77,9 +71,9 @@ VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t in |
|
|
float y = conv(src.translate_y - src.scale_y); |
|
|
float y = conv(src.translate_y - src.scale_y); |
|
|
float height = conv(src.scale_y * 2.0f); |
|
|
float height = conv(src.scale_y * 2.0f); |
|
|
|
|
|
|
|
|
const bool lower_left = regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft; |
|
|
|
|
|
|
|
|
const bool lower_left = regs.window_origin.mode != Tegra::Engines::Maxwell3D::Regs::WindowOrigin::Mode::UpperLeft; |
|
|
const bool y_negate = !device.IsNvViewportSwizzleSupported() && |
|
|
const bool y_negate = !device.IsNvViewportSwizzleSupported() && |
|
|
src.swizzle.y == Maxwell::ViewportSwizzle::NegativeY; |
|
|
|
|
|
|
|
|
src.swizzle.y == Tegra::Engines::Maxwell3D::Regs::ViewportSwizzle::NegativeY; |
|
|
|
|
|
|
|
|
if (lower_left) { |
|
|
if (lower_left) { |
|
|
// Flip by surface clip height
|
|
|
// Flip by surface clip height
|
|
|
@ -93,7 +87,7 @@ VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t in |
|
|
height = -height; |
|
|
height = -height; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const float reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1.0f : 0.0f; |
|
|
|
|
|
|
|
|
const float reduce_z = regs.depth_mode == Tegra::Engines::Maxwell3D::Regs::DepthMode::MinusOneToOne ? 1.0f : 0.0f; |
|
|
VkViewport viewport{ |
|
|
VkViewport viewport{ |
|
|
.x = x, |
|
|
.x = x, |
|
|
.y = y, |
|
|
.y = y, |
|
|
@ -109,7 +103,7 @@ VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t in |
|
|
return viewport; |
|
|
return viewport; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u32 down_shift = 0) { |
|
|
|
|
|
|
|
|
VkRect2D GetScissorState(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index, u32 up_scale = 1, u32 down_shift = 0) { |
|
|
const auto& src = regs.scissor_test[index]; |
|
|
const auto& src = regs.scissor_test[index]; |
|
|
VkRect2D scissor{}; |
|
|
VkRect2D scissor{}; |
|
|
const auto scale_up = [&](s32 value) -> s32 { |
|
|
const auto scale_up = [&](s32 value) -> s32 { |
|
|
@ -126,7 +120,7 @@ VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u3 |
|
|
: std::max<s32>(converted_value + acumm, 1); |
|
|
: std::max<s32>(converted_value + acumm, 1); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const bool lower_left = regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft; |
|
|
|
|
|
|
|
|
const bool lower_left = regs.window_origin.mode != Tegra::Engines::Maxwell3D::Regs::WindowOrigin::Mode::UpperLeft; |
|
|
const s32 clip_height = regs.surface_clip.height; |
|
|
const s32 clip_height = regs.surface_clip.height; |
|
|
|
|
|
|
|
|
// Flip coordinates if lower left
|
|
|
// Flip coordinates if lower left
|
|
|
@ -151,7 +145,7 @@ VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u3 |
|
|
return scissor; |
|
|
return scissor; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
DrawParams MakeDrawParams(const MaxwellDrawState& draw_state, u32 num_instances, bool is_indexed) { |
|
|
|
|
|
|
|
|
DrawParams MakeDrawParams(const Tegra::Engines::DrawManager::State& draw_state, u32 num_instances, bool is_indexed) { |
|
|
DrawParams params{ |
|
|
DrawParams params{ |
|
|
.base_instance = draw_state.base_instance, |
|
|
.base_instance = draw_state.base_instance, |
|
|
.num_instances = num_instances, |
|
|
.num_instances = num_instances, |
|
|
@ -162,11 +156,11 @@ DrawParams MakeDrawParams(const MaxwellDrawState& draw_state, u32 num_instances, |
|
|
}; |
|
|
}; |
|
|
// 6 triangle vertices per quad, base vertex is part of the index
|
|
|
// 6 triangle vertices per quad, base vertex is part of the index
|
|
|
// See BindQuadIndexBuffer for more details
|
|
|
// See BindQuadIndexBuffer for more details
|
|
|
if (draw_state.topology == Maxwell::PrimitiveTopology::Quads) { |
|
|
|
|
|
|
|
|
if (draw_state.topology == Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology::Quads) { |
|
|
params.num_vertices = (params.num_vertices / 4) * 6; |
|
|
params.num_vertices = (params.num_vertices / 4) * 6; |
|
|
params.base_vertex = 0; |
|
|
params.base_vertex = 0; |
|
|
params.is_indexed = true; |
|
|
params.is_indexed = true; |
|
|
} else if (draw_state.topology == Maxwell::PrimitiveTopology::QuadStrip) { |
|
|
|
|
|
|
|
|
} else if (draw_state.topology == Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology::QuadStrip) { |
|
|
params.num_vertices = (params.num_vertices - 2) / 2 * 6; |
|
|
params.num_vertices = (params.num_vertices - 2) / 2 * 6; |
|
|
params.base_vertex = 0; |
|
|
params.base_vertex = 0; |
|
|
params.is_indexed = true; |
|
|
params.is_indexed = true; |
|
|
@ -1107,8 +1101,8 @@ void RasterizerVulkan::HandleTransformFeedback() { |
|
|
GPU::Logging::GPULogger::GetInstance().LogExtensionUsage( |
|
|
GPU::Logging::GPULogger::GetInstance().LogExtensionUsage( |
|
|
"VK_EXT_transform_feedback", "HandleTransformFeedback"); |
|
|
"VK_EXT_transform_feedback", "HandleTransformFeedback"); |
|
|
} |
|
|
} |
|
|
UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderType::TessellationInit) || |
|
|
|
|
|
regs.IsShaderConfigEnabled(Maxwell::ShaderType::Tessellation)); |
|
|
|
|
|
|
|
|
UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Tegra::Engines::Maxwell3D::Regs::ShaderType::TessellationInit) || |
|
|
|
|
|
regs.IsShaderConfigEnabled(Tegra::Engines::Maxwell3D::Regs::ShaderType::Tessellation)); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1121,7 +1115,7 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg |
|
|
float y = static_cast<float>(regs.surface_clip.y); |
|
|
float y = static_cast<float>(regs.surface_clip.y); |
|
|
float width = (std::max)(1.0f, static_cast<float>(regs.surface_clip.width)); |
|
|
float width = (std::max)(1.0f, static_cast<float>(regs.surface_clip.width)); |
|
|
float height = (std::max)(1.0f, static_cast<float>(regs.surface_clip.height)); |
|
|
float height = (std::max)(1.0f, static_cast<float>(regs.surface_clip.height)); |
|
|
if (regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft) { |
|
|
|
|
|
|
|
|
if (regs.window_origin.mode != Tegra::Engines::Maxwell3D::Regs::WindowOrigin::Mode::UpperLeft) { |
|
|
y += height; |
|
|
y += height; |
|
|
height = -height; |
|
|
height = -height; |
|
|
} |
|
|
} |
|
|
@ -1151,7 +1145,7 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg |
|
|
GetViewportState(device, regs, 14, scale), GetViewportState(device, regs, 15, scale), |
|
|
GetViewportState(device, regs, 14, scale), GetViewportState(device, regs, 15, scale), |
|
|
}; |
|
|
}; |
|
|
scheduler.Record([this, viewport_list](vk::CommandBuffer cmdbuf) { |
|
|
scheduler.Record([this, viewport_list](vk::CommandBuffer cmdbuf) { |
|
|
const u32 num_viewports = std::min<u32>(device.GetMaxViewports(), Maxwell::NumViewports); |
|
|
|
|
|
|
|
|
const u32 num_viewports = std::min<u32>(device.GetMaxViewports(), Tegra::Engines::Maxwell3D::Regs::NumViewports); |
|
|
const vk::Span<VkViewport> viewports(viewport_list.data(), num_viewports); |
|
|
const vk::Span<VkViewport> viewports(viewport_list.data(), num_viewports); |
|
|
cmdbuf.SetViewport(0, viewports); |
|
|
cmdbuf.SetViewport(0, viewports); |
|
|
}); |
|
|
}); |
|
|
@ -1166,7 +1160,7 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs |
|
|
u32 y = regs.surface_clip.y; |
|
|
u32 y = regs.surface_clip.y; |
|
|
u32 width = (std::max)(1u, static_cast<u32>(regs.surface_clip.width)); |
|
|
u32 width = (std::max)(1u, static_cast<u32>(regs.surface_clip.width)); |
|
|
u32 height = (std::max)(1u, static_cast<u32>(regs.surface_clip.height)); |
|
|
u32 height = (std::max)(1u, static_cast<u32>(regs.surface_clip.height)); |
|
|
if (regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft) { |
|
|
|
|
|
|
|
|
if (regs.window_origin.mode != Tegra::Engines::Maxwell3D::Regs::WindowOrigin::Mode::UpperLeft) { |
|
|
y = regs.surface_clip.height - (y + height); |
|
|
y = regs.surface_clip.height - (y + height); |
|
|
} |
|
|
} |
|
|
VkRect2D scissor{}; |
|
|
VkRect2D scissor{}; |
|
|
@ -1204,7 +1198,7 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs |
|
|
GetScissorState(regs, 15, up_scale, down_shift), |
|
|
GetScissorState(regs, 15, up_scale, down_shift), |
|
|
}; |
|
|
}; |
|
|
scheduler.Record([this, scissor_list](vk::CommandBuffer cmdbuf) { |
|
|
scheduler.Record([this, scissor_list](vk::CommandBuffer cmdbuf) { |
|
|
const u32 num_scissors = std::min<u32>(device.GetMaxViewports(), Maxwell::NumViewports); |
|
|
|
|
|
|
|
|
const u32 num_scissors = std::min<u32>(device.GetMaxViewports(), Tegra::Engines::Maxwell3D::Regs::NumViewports); |
|
|
const vk::Span<VkRect2D> scissors(scissor_list.data(), num_scissors); |
|
|
const vk::Span<VkRect2D> scissors(scissor_list.data(), num_scissors); |
|
|
cmdbuf.SetScissor(0, scissors); |
|
|
cmdbuf.SetScissor(0, scissors); |
|
|
}); |
|
|
}); |
|
|
@ -1556,11 +1550,11 @@ void RasterizerVulkan::UpdateDepthClampEnable(Tegra::Engines::Maxwell3D::Regs& r |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
bool is_enabled = !(regs.viewport_clip_control.geometry_clip == |
|
|
bool is_enabled = !(regs.viewport_clip_control.geometry_clip == |
|
|
Maxwell::ViewportClipControl::GeometryClip::Passthrough || |
|
|
|
|
|
|
|
|
Tegra::Engines::Maxwell3D::Regs::ViewportClipControl::GeometryClip::Passthrough || |
|
|
regs.viewport_clip_control.geometry_clip == |
|
|
regs.viewport_clip_control.geometry_clip == |
|
|
Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ || |
|
|
|
|
|
|
|
|
Tegra::Engines::Maxwell3D::Regs::ViewportClipControl::GeometryClip::FrustumXYZ || |
|
|
regs.viewport_clip_control.geometry_clip == |
|
|
regs.viewport_clip_control.geometry_clip == |
|
|
Maxwell::ViewportClipControl::GeometryClip::FrustumZ); |
|
|
|
|
|
|
|
|
Tegra::Engines::Maxwell3D::Regs::ViewportClipControl::GeometryClip::FrustumZ); |
|
|
scheduler.Record( |
|
|
scheduler.Record( |
|
|
[is_enabled](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthClampEnableEXT(is_enabled); }); |
|
|
[is_enabled](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthClampEnableEXT(is_enabled); }); |
|
|
} |
|
|
} |
|
|
@ -1627,16 +1621,16 @@ void RasterizerVulkan::UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs) { |
|
|
if (!state_tracker.TouchStencilOp()) { |
|
|
if (!state_tracker.TouchStencilOp()) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
const Maxwell::StencilOp::Op fail = regs.stencil_front_op.fail; |
|
|
|
|
|
const Maxwell::StencilOp::Op zfail = regs.stencil_front_op.zfail; |
|
|
|
|
|
const Maxwell::StencilOp::Op zpass = regs.stencil_front_op.zpass; |
|
|
|
|
|
const Maxwell::ComparisonOp compare = regs.stencil_front_op.func; |
|
|
|
|
|
|
|
|
const Tegra::Engines::Maxwell3D::Regs::StencilOp::Op fail = regs.stencil_front_op.fail; |
|
|
|
|
|
const Tegra::Engines::Maxwell3D::Regs::StencilOp::Op zfail = regs.stencil_front_op.zfail; |
|
|
|
|
|
const Tegra::Engines::Maxwell3D::Regs::StencilOp::Op zpass = regs.stencil_front_op.zpass; |
|
|
|
|
|
const Tegra::Engines::Maxwell3D::Regs::ComparisonOp compare = regs.stencil_front_op.func; |
|
|
if (regs.stencil_two_side_enable) { |
|
|
if (regs.stencil_two_side_enable) { |
|
|
// Separate stencil op per face
|
|
|
// Separate stencil op per face
|
|
|
const Maxwell::StencilOp::Op back_fail = regs.stencil_back_op.fail; |
|
|
|
|
|
const Maxwell::StencilOp::Op back_zfail = regs.stencil_back_op.zfail; |
|
|
|
|
|
const Maxwell::StencilOp::Op back_zpass = regs.stencil_back_op.zpass; |
|
|
|
|
|
const Maxwell::ComparisonOp back_compare = regs.stencil_back_op.func; |
|
|
|
|
|
|
|
|
const Tegra::Engines::Maxwell3D::Regs::StencilOp::Op back_fail = regs.stencil_back_op.fail; |
|
|
|
|
|
const Tegra::Engines::Maxwell3D::Regs::StencilOp::Op back_zfail = regs.stencil_back_op.zfail; |
|
|
|
|
|
const Tegra::Engines::Maxwell3D::Regs::StencilOp::Op back_zpass = regs.stencil_back_op.zpass; |
|
|
|
|
|
const Tegra::Engines::Maxwell3D::Regs::ComparisonOp back_compare = regs.stencil_back_op.func; |
|
|
scheduler.Record([fail, zfail, zpass, compare, back_fail, back_zfail, back_zpass, |
|
|
scheduler.Record([fail, zfail, zpass, compare, back_fail, back_zfail, back_zpass, |
|
|
back_compare](vk::CommandBuffer cmdbuf) { |
|
|
back_compare](vk::CommandBuffer cmdbuf) { |
|
|
cmdbuf.SetStencilOpEXT(VK_STENCIL_FACE_FRONT_BIT, MaxwellToVK::StencilOp(fail), |
|
|
cmdbuf.SetStencilOpEXT(VK_STENCIL_FACE_FRONT_BIT, MaxwellToVK::StencilOp(fail), |
|
|
@ -1673,8 +1667,8 @@ void RasterizerVulkan::UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (state_tracker.TouchColorMask()) { |
|
|
if (state_tracker.TouchColorMask()) { |
|
|
std::array<VkColorComponentFlags, Maxwell::NumRenderTargets> setup_masks{}; |
|
|
|
|
|
for (size_t index = 0; index < Maxwell::NumRenderTargets; index++) { |
|
|
|
|
|
|
|
|
std::array<VkColorComponentFlags, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> setup_masks{}; |
|
|
|
|
|
for (size_t index = 0; index < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; index++) { |
|
|
const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : index]; |
|
|
const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : index]; |
|
|
auto& current = setup_masks[index]; |
|
|
auto& current = setup_masks[index]; |
|
|
if (mask.R) { |
|
|
if (mask.R) { |
|
|
@ -1696,7 +1690,7 @@ void RasterizerVulkan::UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (state_tracker.TouchBlendEnable()) { |
|
|
if (state_tracker.TouchBlendEnable()) { |
|
|
std::array<VkBool32, Maxwell::NumRenderTargets> setup_enables{}; |
|
|
|
|
|
|
|
|
std::array<VkBool32, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> setup_enables{}; |
|
|
std::ranges::transform( |
|
|
std::ranges::transform( |
|
|
regs.blend.enable, setup_enables.begin(), |
|
|
regs.blend.enable, setup_enables.begin(), |
|
|
[&](const auto& is_enabled) { return is_enabled != 0 ? VK_TRUE : VK_FALSE; }); |
|
|
[&](const auto& is_enabled) { return is_enabled != 0 ? VK_TRUE : VK_FALSE; }); |
|
|
@ -1706,7 +1700,7 @@ void RasterizerVulkan::UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (state_tracker.TouchBlendEquations()) { |
|
|
if (state_tracker.TouchBlendEquations()) { |
|
|
std::array<VkColorBlendEquationEXT, Maxwell::NumRenderTargets> setup_blends{}; |
|
|
|
|
|
|
|
|
std::array<VkColorBlendEquationEXT, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> setup_blends{}; |
|
|
|
|
|
|
|
|
const auto blend_setup = [&](auto& host_blend, const auto& guest_blend) { |
|
|
const auto blend_setup = [&](auto& host_blend, const auto& guest_blend) { |
|
|
host_blend.srcColorBlendFactor = MaxwellToVK::BlendFactor(guest_blend.color_source); |
|
|
host_blend.srcColorBlendFactor = MaxwellToVK::BlendFactor(guest_blend.color_source); |
|
|
@ -1732,12 +1726,12 @@ void RasterizerVulkan::UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Copy first blend state to all other targets
|
|
|
// Copy first blend state to all other targets
|
|
|
for (size_t index = 1; index < Maxwell::NumRenderTargets; index++) { |
|
|
|
|
|
|
|
|
for (size_t index = 1; index < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; index++) { |
|
|
setup_blends[index] = setup_blends[0]; |
|
|
setup_blends[index] = setup_blends[0]; |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
// Per-target blending
|
|
|
// Per-target blending
|
|
|
for (size_t index = 0; index < Maxwell::NumRenderTargets; index++) { |
|
|
|
|
|
|
|
|
for (size_t index = 0; index < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; index++) { |
|
|
blend_setup(setup_blends[index], regs.blend_per_target[index]); |
|
|
blend_setup(setup_blends[index], regs.blend_per_target[index]); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -1771,13 +1765,13 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs) |
|
|
// generating dirty state. Track the highest dirty attribute and update all attributes until
|
|
|
// generating dirty state. Track the highest dirty attribute and update all attributes until
|
|
|
// that one.
|
|
|
// that one.
|
|
|
size_t highest_dirty_attr{}; |
|
|
size_t highest_dirty_attr{}; |
|
|
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) { |
|
|
|
|
|
|
|
|
for (size_t index = 0; index < Tegra::Engines::Maxwell3D::Regs::NumVertexAttributes; ++index) { |
|
|
if (dirty[Dirty::VertexAttribute0 + index]) { |
|
|
if (dirty[Dirty::VertexAttribute0 + index]) { |
|
|
highest_dirty_attr = index; |
|
|
highest_dirty_attr = index; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
for (size_t index = 0; index < highest_dirty_attr; ++index) { |
|
|
for (size_t index = 0; index < highest_dirty_attr; ++index) { |
|
|
const Maxwell::VertexAttribute attribute{regs.vertex_attrib_format[index]}; |
|
|
|
|
|
|
|
|
const Tegra::Engines::Maxwell3D::Regs::VertexAttribute attribute{regs.vertex_attrib_format[index]}; |
|
|
const u32 binding{attribute.buffer}; |
|
|
const u32 binding{attribute.buffer}; |
|
|
dirty[Dirty::VertexAttribute0 + index] = false; |
|
|
dirty[Dirty::VertexAttribute0 + index] = false; |
|
|
dirty[Dirty::VertexBinding0 + static_cast<size_t>(binding)] = true; |
|
|
dirty[Dirty::VertexBinding0 + static_cast<size_t>(binding)] = true; |
|
|
@ -1792,7 +1786,7 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs) |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) { |
|
|
|
|
|
|
|
|
for (size_t index = 0; index < Tegra::Engines::Maxwell3D::Regs::NumVertexAttributes; ++index) { |
|
|
if (!dirty[Dirty::VertexBinding0 + index]) { |
|
|
if (!dirty[Dirty::VertexBinding0 + index]) { |
|
|
continue; |
|
|
continue; |
|
|
} |
|
|
} |
|
|
|