mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-05-31 15:53:17 +00:00
video_core: Add constant buffer support (#147)
This commit is contained in:
parent
3c90b8ac00
commit
8dfa5782b2
26 changed files with 395 additions and 56 deletions
|
@ -27,6 +27,7 @@ struct Buffer {
|
|||
BitField<15, 4, DataFormat> data_format;
|
||||
BitField<19, 2, u32> element_size;
|
||||
BitField<21, 2, u32> index_stride;
|
||||
BitField<23, 1, u32> add_tid_enable;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <boost/container/small_vector.hpp>
|
||||
#include <boost/container/static_vector.hpp>
|
||||
|
||||
#include "common/assert.h"
|
||||
|
@ -25,9 +26,11 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul
|
|||
stages[i] = *infos[i];
|
||||
}
|
||||
|
||||
desc_layout = BuildSetLayout();
|
||||
const vk::DescriptorSetLayout set_layout = *desc_layout;
|
||||
const vk::PipelineLayoutCreateInfo layout_info = {
|
||||
.setLayoutCount = 0U,
|
||||
.pSetLayouts = nullptr,
|
||||
.setLayoutCount = 1U,
|
||||
.pSetLayouts = &set_layout,
|
||||
.pushConstantRangeCount = 0,
|
||||
.pPushConstantRanges = nullptr,
|
||||
};
|
||||
|
@ -196,10 +199,32 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul
|
|||
|
||||
GraphicsPipeline::~GraphicsPipeline() = default;
|
||||
|
||||
vk::UniqueDescriptorSetLayout GraphicsPipeline::BuildSetLayout() const {
|
||||
u32 binding{};
|
||||
boost::container::small_vector<vk::DescriptorSetLayoutBinding, 32> bindings;
|
||||
for (const auto& stage : stages) {
|
||||
for (const auto& buffer : stage.buffers) {
|
||||
bindings.push_back({
|
||||
.binding = binding++,
|
||||
.descriptorType = vk::DescriptorType::eStorageBuffer,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment,
|
||||
});
|
||||
}
|
||||
}
|
||||
const vk::DescriptorSetLayoutCreateInfo desc_layout_ci = {
|
||||
.flags = vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR,
|
||||
.bindingCount = static_cast<u32>(bindings.size()),
|
||||
.pBindings = bindings.data(),
|
||||
};
|
||||
return instance.GetDevice().createDescriptorSetLayoutUnique(desc_layout_ci);
|
||||
}
|
||||
|
||||
void GraphicsPipeline::BindResources(Core::MemoryManager* memory) const {
|
||||
std::array<vk::Buffer, MaxVertexBufferCount> buffers;
|
||||
std::array<vk::DeviceSize, MaxVertexBufferCount> offsets;
|
||||
|
||||
// Bind vertex buffer.
|
||||
const auto& vs_info = stages[0];
|
||||
const size_t num_buffers = vs_info.vs_inputs.size();
|
||||
for (u32 i = 0; i < num_buffers; ++i) {
|
||||
|
@ -210,6 +235,33 @@ void GraphicsPipeline::BindResources(Core::MemoryManager* memory) const {
|
|||
|
||||
const auto cmdbuf = scheduler.CommandBuffer();
|
||||
cmdbuf.bindVertexBuffers(0, num_buffers, buffers.data(), offsets.data());
|
||||
|
||||
// Bind resource buffers and textures.
|
||||
boost::container::static_vector<vk::DescriptorBufferInfo, 4> buffer_infos;
|
||||
boost::container::small_vector<vk::WriteDescriptorSet, 16> set_writes;
|
||||
u32 binding{};
|
||||
|
||||
for (const auto& stage : stages) {
|
||||
for (const auto& buffer : stage.buffers) {
|
||||
const auto vsharp = stage.ReadUd<AmdGpu::Buffer>(buffer.sgpr_base, buffer.dword_offset);
|
||||
const auto [vk_buffer, offset] = memory->GetVulkanBuffer(vsharp.base_address);
|
||||
buffer_infos.push_back({
|
||||
.buffer = vk_buffer,
|
||||
.offset = offset,
|
||||
.range = vsharp.stride * vsharp.num_records,
|
||||
});
|
||||
set_writes.push_back({
|
||||
.dstSet = VK_NULL_HANDLE,
|
||||
.dstBinding = binding,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eStorageBuffer,
|
||||
.pBufferInfo = &buffer_infos.back(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
cmdbuf.pushDescriptorSetKHR(vk::PipelineBindPoint::eGraphics, *pipeline_layout, 0, set_writes);
|
||||
}
|
||||
|
||||
} // namespace Vulkan
|
||||
|
|
|
@ -54,12 +54,16 @@ public:
|
|||
return *pipeline;
|
||||
}
|
||||
|
||||
private:
|
||||
vk::UniqueDescriptorSetLayout BuildSetLayout() const;
|
||||
|
||||
private:
|
||||
const Instance& instance;
|
||||
Scheduler& scheduler;
|
||||
vk::UniquePipeline pipeline;
|
||||
vk::UniquePipelineLayout pipeline_layout;
|
||||
std::array<Shader::Info, MaxShaderStages> stages;
|
||||
vk::UniqueDescriptorSetLayout desc_layout;
|
||||
std::array<Shader::Info, MaxShaderStages> stages{};
|
||||
PipelineKey key;
|
||||
};
|
||||
|
||||
|
|
|
@ -150,6 +150,7 @@ bool Instance::CreateDevice() {
|
|||
tooling_info = add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME);
|
||||
custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||
index_type_uint8 = add_extension(VK_KHR_INDEX_TYPE_UINT8_EXTENSION_NAME);
|
||||
add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
|
||||
const auto family_properties = physical_device.getQueueFamilyProperties();
|
||||
if (family_properties.empty()) {
|
||||
|
|
|
@ -123,7 +123,12 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreatePipeline() {
|
|||
std::move(info));
|
||||
|
||||
// Compile IR to SPIR-V
|
||||
const auto spv_code = Shader::Backend::SPIRV::EmitSPIRV(Shader::Profile{}, programs[i]);
|
||||
const auto profile = Shader::Profile{.supported_spirv = 0x00010600U};
|
||||
const auto spv_code = Shader::Backend::SPIRV::EmitSPIRV(profile, programs[i]);
|
||||
std::ofstream file("shader0.spv", std::ios::out | std::ios::binary);
|
||||
file.write((const char*)spv_code.data(), spv_code.size() * 4);
|
||||
file.close();
|
||||
|
||||
stages[i] = CompileSPV(spv_code, instance.GetDevice());
|
||||
infos[i] = &programs[i].info;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ void Rasterizer::Draw(bool is_indexed) {
|
|||
if (is_indexed) {
|
||||
cmdbuf.drawIndexed(num_indices, regs.num_instances.NumInstances(), 0, 0, 0);
|
||||
} else {
|
||||
cmdbuf.draw(regs.num_indices, regs.num_instances.NumInstances(), 0, 0);
|
||||
cmdbuf.draw(num_indices, regs.num_instances.NumInstances(), 0, 0);
|
||||
}
|
||||
cmdbuf.endRendering();
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ u32 Rasterizer::SetupIndexBuffer(bool& is_indexed) {
|
|||
return index_size / sizeof(u16);
|
||||
}
|
||||
if (!is_indexed) {
|
||||
return 0;
|
||||
return regs.num_indices;
|
||||
}
|
||||
|
||||
const VAddr index_address = regs.index_base_address.Address();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue