video_core: Add constant buffer support (#147)

This commit is contained in:
TheTurtle 2024-05-26 15:51:35 +03:00 committed by GitHub
parent 3c90b8ac00
commit 8dfa5782b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 395 additions and 56 deletions

View file

@ -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;
};
};

View file

@ -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

View file

@ -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;
};

View file

@ -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()) {

View file

@ -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;
}

View file

@ -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();