mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2024-12-28 18:46:06 +00:00
vulkan: Use dynamic vertex buffer strides when dynamic bindings unavailable. (#1164)
This commit is contained in:
parent
82c7c6aed1
commit
bf3e43b016
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
|
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue