Skip to content

Commit

Permalink
vulkan: Use dynamic vertex buffer strides when dynamic bindings unava…
Browse files Browse the repository at this point in the history
…ilable. (shadps4-emu#1164)
  • Loading branch information
squidbus authored Oct 1, 2024
1 parent 82c7c6a commit bf3e43b
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 26 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)

if(APPLE)
enable_language(OBJC)
set(CMAKE_OSX_DEPLOYMENT_TARGET 11)
set(CMAKE_OSX_DEPLOYMENT_TARGET 14)
endif()

if (NOT CMAKE_BUILD_TYPE)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ Check the build instructions for [**Linux**](https://github.com/shadps4-emu/shad
Check the build instructions for [**macOS**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-macos.md).

> [!IMPORTANT]
> macOS users need at least macOS 15 on Apple Silicon-based Mac devices and at least macOS 11 on Intel-based Mac devices.
> macOS users need at least macOS 15 on Apple Silicon-based Mac devices and at least macOS 14 on Intel-based Mac devices.
# Debugging and reporting issues

Expand Down
11 changes: 10 additions & 1 deletion src/video_core/buffer_cache/buffer_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ bool BufferCache::BindVertexBuffers(const Shader::Info& vs_info) {

std::array<vk::Buffer, NumVertexBuffers> host_buffers;
std::array<vk::DeviceSize, NumVertexBuffers> host_offsets;
std::array<vk::DeviceSize, NumVertexBuffers> host_sizes;
std::array<vk::DeviceSize, NumVertexBuffers> host_strides;
boost::container::static_vector<AmdGpu::Buffer, NumVertexBuffers> guest_buffers;

struct BufferRange {
Expand Down Expand Up @@ -193,11 +195,18 @@ bool BufferCache::BindVertexBuffers(const Shader::Info& vs_info) {

host_buffers[i] = host_buffer->vk_buffer;
host_offsets[i] = host_buffer->offset + buffer.base_address - host_buffer->base_address;
host_sizes[i] = buffer.GetSize();
host_strides[i] = buffer.GetStride();
}

if (num_buffers > 0) {
const auto cmdbuf = scheduler.CommandBuffer();
cmdbuf.bindVertexBuffers(0, num_buffers, host_buffers.data(), host_offsets.data());
if (instance.IsVertexInputDynamicState()) {
cmdbuf.bindVertexBuffers(0, num_buffers, host_buffers.data(), host_offsets.data());
} else {
cmdbuf.bindVertexBuffers2EXT(0, num_buffers, host_buffers.data(), host_offsets.data(),
host_sizes.data(), host_strides.data());
}
}

return has_step_rate;
Expand Down
52 changes: 30 additions & 22 deletions src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,28 +46,34 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul

boost::container::static_vector<vk::VertexInputBindingDescription, 32> vertex_bindings;
boost::container::static_vector<vk::VertexInputAttributeDescription, 32> vertex_attributes;
const auto& vs_info = stages[u32(Shader::Stage::Vertex)];
for (const auto& input : vs_info->vs_inputs) {
if (input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate0 ||
input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate1) {
// Skip attribute binding as the data will be pulled by shader
continue;
}
if (!instance.IsVertexInputDynamicState()) {
const auto& vs_info = stages[u32(Shader::Stage::Vertex)];
for (const auto& input : vs_info->vs_inputs) {
if (input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate0 ||
input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate1) {
// Skip attribute binding as the data will be pulled by shader
continue;
}

const auto buffer = vs_info->ReadUd<AmdGpu::Buffer>(input.sgpr_base, input.dword_offset);
vertex_attributes.push_back({
.location = input.binding,
.binding = input.binding,
.format = LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt()),
.offset = 0,
});
vertex_bindings.push_back({
.binding = input.binding,
.stride = buffer.GetStride(),
.inputRate = input.instance_step_rate == Shader::Info::VsInput::None
? vk::VertexInputRate::eVertex
: vk::VertexInputRate::eInstance,
});
const auto buffer =
vs_info->ReadUd<AmdGpu::Buffer>(input.sgpr_base, input.dword_offset);
if (buffer.GetSize() == 0) {
continue;
}
vertex_attributes.push_back({
.location = input.binding,
.binding = input.binding,
.format = LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt()),
.offset = 0,
});
vertex_bindings.push_back({
.binding = input.binding,
.stride = buffer.GetStride(),
.inputRate = input.instance_step_rate == Shader::Info::VsInput::None
? vk::VertexInputRate::eVertex
: vk::VertexInputRate::eInstance,
});
}
}

const vk::PipelineVertexInputStateCreateInfo vertex_input_info = {
Expand Down Expand Up @@ -147,6 +153,8 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul
}
if (instance.IsVertexInputDynamicState()) {
dynamic_states.push_back(vk::DynamicState::eVertexInputEXT);
} else {
dynamic_states.push_back(vk::DynamicState::eVertexInputBindingStrideEXT);
}

const vk::PipelineDynamicStateCreateInfo dynamic_info = {
Expand Down Expand Up @@ -273,7 +281,7 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul
.pNext = &pipeline_rendering_ci,
.stageCount = static_cast<u32>(shader_stages.size()),
.pStages = shader_stages.data(),
.pVertexInputState = &vertex_input_info,
.pVertexInputState = !instance.IsVertexInputDynamicState() ? &vertex_input_info : nullptr,
.pInputAssemblyState = &input_assembly,
.pViewportState = &viewport_info,
.pRasterizationState = &raster_state,
Expand Down
1 change: 1 addition & 0 deletions src/video_core/renderer_vulkan/vk_graphics_pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct GraphicsPipelineKey {
Liverpool::ColorBufferMask cb_shader_mask;
std::array<Liverpool::BlendControl, Liverpool::NumColorBuffers> blend_controls;
std::array<vk::ColorComponentFlags, Liverpool::NumColorBuffers> write_masks;
std::array<vk::Format, MaxVertexBufferCount> vertex_buffer_formats;

bool operator==(const GraphicsPipelineKey& key) const noexcept {
return std::memcmp(this, &key, sizeof(key)) == 0;
Expand Down
1 change: 1 addition & 0 deletions src/video_core/renderer_vulkan/vk_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ bool Instance::CreateDevice() {
add_extension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME);
add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);

#ifdef __APPLE__
// Required by Vulkan spec if supported.
Expand Down
22 changes: 21 additions & 1 deletion src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ bool PipelineCache::RefreshGraphicsKey() {
key.blend_controls.fill({});
key.write_masks.fill({});
key.mrt_swizzles.fill(Liverpool::ColorBuffer::SwapMode::Standard);
key.vertex_buffer_formats.fill(vk::Format::eUndefined);

// First pass of bindings check to idenitfy formats and swizzles and pass them to rhe shader
// recompiler.
Expand Down Expand Up @@ -310,7 +311,26 @@ bool PipelineCache::RefreshGraphicsKey() {
std::tie(infos[i], modules[i], key.stage_hashes[i]) = GetProgram(stage, params, binding);
}

const auto* fs_info = infos[u32(Shader::Stage::Fragment)];
const auto* vs_info = infos[static_cast<u32>(Shader::Stage::Vertex)];
if (vs_info && !instance.IsVertexInputDynamicState()) {
u32 vertex_binding = 0;
for (const auto& input : vs_info->vs_inputs) {
if (input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate0 ||
input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate1) {
continue;
}
const auto& buffer =
vs_info->ReadUd<AmdGpu::Buffer>(input.sgpr_base, input.dword_offset);
if (buffer.GetSize() == 0) {
continue;
}
ASSERT(vertex_binding < MaxVertexBufferCount);
key.vertex_buffer_formats[vertex_binding++] =
Vulkan::LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt());
}
}

const auto* fs_info = infos[static_cast<u32>(Shader::Stage::Fragment)];
key.mrt_mask = fs_info ? fs_info->mrt_mask : 0u;

// Second pass to fill remain CB pipeline key data
Expand Down

0 comments on commit bf3e43b

Please sign in to comment.