mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-05-29 23:03:18 +00:00
shader_recompiler: Additional scope handling and user data as push constants (#1013)
* shader_recompiler: Use push constants for user data regs * shader: Add some GR2 instructions * shader: Add some instructions * shader: Add instructions for knack * touchups * spirv: Better names * buffer_cache: Ignore non gpu modified images * clang format * Add log * more fixes
This commit is contained in:
parent
fb5bc371cb
commit
ee38eec7fe
23 changed files with 180 additions and 87 deletions
|
@ -581,13 +581,16 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr,
|
|||
return false;
|
||||
}
|
||||
Image& image = texture_cache.GetImage(image_id);
|
||||
if (False(image.flags & ImageFlagBits::GpuModified)) {
|
||||
return false;
|
||||
}
|
||||
ASSERT_MSG(device_addr == image.info.guest_address,
|
||||
"Texel buffer aliases image subresources {:x} : {:x}", device_addr,
|
||||
image.info.guest_address);
|
||||
boost::container::small_vector<vk::BufferImageCopy, 8> copies;
|
||||
u32 offset = buffer.Offset(image.cpu_addr);
|
||||
const u32 num_layers = image.info.resources.layers;
|
||||
u32 total_size = 0;
|
||||
const u32 max_offset = offset + size;
|
||||
for (u32 m = 0; m < image.info.resources.levels; m++) {
|
||||
const u32 width = std::max(image.info.size.width >> m, 1u);
|
||||
const u32 height = std::max(image.info.size.height >> m, 1u);
|
||||
|
@ -595,7 +598,7 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr,
|
|||
image.info.props.is_volume ? std::max(image.info.size.depth >> m, 1u) : 1u;
|
||||
const auto& [mip_size, mip_pitch, mip_height, mip_ofs] = image.info.mips_layout[m];
|
||||
offset += mip_ofs * num_layers;
|
||||
if (offset + (mip_size * num_layers) > buffer.SizeBytes()) {
|
||||
if (offset + (mip_size * num_layers) > max_offset) {
|
||||
break;
|
||||
}
|
||||
copies.push_back({
|
||||
|
@ -611,7 +614,6 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr,
|
|||
.imageOffset = {0, 0, 0},
|
||||
.imageExtent = {width, height, depth},
|
||||
});
|
||||
total_size += mip_size * num_layers;
|
||||
}
|
||||
if (!copies.empty()) {
|
||||
scheduler.EndRendering();
|
||||
|
|
|
@ -112,10 +112,11 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache,
|
|||
boost::container::small_vector<vk::WriteDescriptorSet, 16> set_writes;
|
||||
boost::container::small_vector<vk::BufferMemoryBarrier2, 16> buffer_barriers;
|
||||
Shader::PushData push_data{};
|
||||
u32 binding{};
|
||||
Shader::Backend::Bindings binding{};
|
||||
|
||||
image_infos.clear();
|
||||
|
||||
info->PushUd(binding, push_data);
|
||||
for (const auto& desc : info->buffers) {
|
||||
bool is_storage = true;
|
||||
if (desc.is_gds_buffer) {
|
||||
|
@ -147,21 +148,20 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache,
|
|||
buffer_cache.ObtainBuffer(address, size, desc.is_written);
|
||||
const u32 offset_aligned = Common::AlignDown(offset, alignment);
|
||||
const u32 adjust = offset - offset_aligned;
|
||||
if (adjust != 0) {
|
||||
ASSERT(adjust % 4 == 0);
|
||||
push_data.AddOffset(binding, adjust);
|
||||
}
|
||||
ASSERT(adjust % 4 == 0);
|
||||
push_data.AddOffset(binding.buffer, adjust);
|
||||
buffer_infos.emplace_back(vk_buffer->Handle(), offset_aligned, size + adjust);
|
||||
}
|
||||
set_writes.push_back({
|
||||
.dstSet = VK_NULL_HANDLE,
|
||||
.dstBinding = binding++,
|
||||
.dstBinding = binding.unified++,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = is_storage ? vk::DescriptorType::eStorageBuffer
|
||||
: vk::DescriptorType::eUniformBuffer,
|
||||
.pBufferInfo = &buffer_infos.back(),
|
||||
});
|
||||
++binding.buffer;
|
||||
}
|
||||
|
||||
for (const auto& desc : info->texture_buffers) {
|
||||
|
@ -188,10 +188,8 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache,
|
|||
"Texel buffer stride must match format stride");
|
||||
const u32 offset_aligned = Common::AlignDown(offset, alignment);
|
||||
const u32 adjust = offset - offset_aligned;
|
||||
if (adjust != 0) {
|
||||
ASSERT(adjust % fmt_stride == 0);
|
||||
push_data.AddOffset(binding, adjust / fmt_stride);
|
||||
}
|
||||
ASSERT(adjust % fmt_stride == 0);
|
||||
push_data.AddOffset(binding.buffer, adjust / fmt_stride);
|
||||
buffer_view = vk_buffer->View(offset_aligned, size + adjust, desc.is_written,
|
||||
vsharp.GetDataFmt(), vsharp.GetNumberFmt());
|
||||
if (auto barrier =
|
||||
|
@ -206,13 +204,14 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache,
|
|||
}
|
||||
set_writes.push_back({
|
||||
.dstSet = VK_NULL_HANDLE,
|
||||
.dstBinding = binding++,
|
||||
.dstBinding = binding.unified++,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = desc.is_written ? vk::DescriptorType::eStorageTexelBuffer
|
||||
: vk::DescriptorType::eUniformTexelBuffer,
|
||||
.pTexelBufferView = &buffer_view,
|
||||
});
|
||||
++binding.buffer;
|
||||
}
|
||||
|
||||
BindTextures(texture_cache, *info, binding, set_writes);
|
||||
|
@ -226,7 +225,7 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache,
|
|||
image_infos.emplace_back(vk_sampler, VK_NULL_HANDLE, vk::ImageLayout::eGeneral);
|
||||
set_writes.push_back({
|
||||
.dstSet = VK_NULL_HANDLE,
|
||||
.dstBinding = binding++,
|
||||
.dstBinding = binding.unified++,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampler,
|
||||
|
|
|
@ -83,8 +83,9 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul
|
|||
.topology = LiverpoolToVK::PrimitiveType(key.prim_type),
|
||||
.primitiveRestartEnable = key.enable_primitive_restart != 0,
|
||||
};
|
||||
ASSERT_MSG(!key.enable_primitive_restart || key.primitive_restart_index == 0xFFFF,
|
||||
"Primitive restart index other than 0xFFFF is not supported yet");
|
||||
ASSERT_MSG(!key.enable_primitive_restart || key.primitive_restart_index == 0xFFFF ||
|
||||
key.primitive_restart_index == 0xFFFFFFFF,
|
||||
"Primitive restart index other than -1 is not supported yet");
|
||||
|
||||
const vk::PipelineRasterizationStateCreateInfo raster_state = {
|
||||
.depthClampEnable = false,
|
||||
|
@ -356,7 +357,7 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs,
|
|||
boost::container::small_vector<vk::WriteDescriptorSet, 16> set_writes;
|
||||
boost::container::small_vector<vk::BufferMemoryBarrier2, 16> buffer_barriers;
|
||||
Shader::PushData push_data{};
|
||||
u32 binding{};
|
||||
Shader::Backend::Bindings binding{};
|
||||
|
||||
image_infos.clear();
|
||||
|
||||
|
@ -368,6 +369,7 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs,
|
|||
push_data.step0 = regs.vgt_instance_step_rate_0;
|
||||
push_data.step1 = regs.vgt_instance_step_rate_1;
|
||||
}
|
||||
stage->PushUd(binding, push_data);
|
||||
for (const auto& buffer : stage->buffers) {
|
||||
const auto vsharp = buffer.GetSharp(*stage);
|
||||
const bool is_storage = buffer.IsStorage(vsharp);
|
||||
|
@ -383,10 +385,8 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs,
|
|||
buffer_cache.ObtainBuffer(address, size, buffer.is_written);
|
||||
const u32 offset_aligned = Common::AlignDown(offset, alignment);
|
||||
const u32 adjust = offset - offset_aligned;
|
||||
if (adjust != 0) {
|
||||
ASSERT(adjust % 4 == 0);
|
||||
push_data.AddOffset(binding, adjust);
|
||||
}
|
||||
ASSERT(adjust % 4 == 0);
|
||||
push_data.AddOffset(binding.buffer, adjust);
|
||||
buffer_infos.emplace_back(vk_buffer->Handle(), offset_aligned, size + adjust);
|
||||
} else if (instance.IsNullDescriptorSupported()) {
|
||||
buffer_infos.emplace_back(VK_NULL_HANDLE, 0, VK_WHOLE_SIZE);
|
||||
|
@ -396,13 +396,14 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs,
|
|||
}
|
||||
set_writes.push_back({
|
||||
.dstSet = VK_NULL_HANDLE,
|
||||
.dstBinding = binding++,
|
||||
.dstBinding = binding.unified++,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = is_storage ? vk::DescriptorType::eStorageBuffer
|
||||
: vk::DescriptorType::eUniformBuffer,
|
||||
.pBufferInfo = &buffer_infos.back(),
|
||||
});
|
||||
++binding.buffer;
|
||||
}
|
||||
|
||||
for (const auto& desc : stage->texture_buffers) {
|
||||
|
@ -419,10 +420,8 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs,
|
|||
"Texel buffer stride must match format stride");
|
||||
const u32 offset_aligned = Common::AlignDown(offset, alignment);
|
||||
const u32 adjust = offset - offset_aligned;
|
||||
if (adjust != 0) {
|
||||
ASSERT(adjust % fmt_stride == 0);
|
||||
push_data.AddOffset(binding, adjust / fmt_stride);
|
||||
}
|
||||
ASSERT(adjust % fmt_stride == 0);
|
||||
push_data.AddOffset(binding.buffer, adjust / fmt_stride);
|
||||
buffer_view = vk_buffer->View(offset_aligned, size + adjust, desc.is_written,
|
||||
vsharp.GetDataFmt(), vsharp.GetNumberFmt());
|
||||
const auto dst_access = desc.is_written ? vk::AccessFlagBits2::eShaderWrite
|
||||
|
@ -437,13 +436,14 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs,
|
|||
}
|
||||
set_writes.push_back({
|
||||
.dstSet = VK_NULL_HANDLE,
|
||||
.dstBinding = binding++,
|
||||
.dstBinding = binding.unified++,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = desc.is_written ? vk::DescriptorType::eStorageTexelBuffer
|
||||
: vk::DescriptorType::eUniformTexelBuffer,
|
||||
.pTexelBufferView = &buffer_view,
|
||||
});
|
||||
++binding.buffer;
|
||||
}
|
||||
|
||||
BindTextures(texture_cache, *stage, binding, set_writes);
|
||||
|
@ -463,7 +463,7 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs,
|
|||
image_infos.emplace_back(vk_sampler, VK_NULL_HANDLE, vk::ImageLayout::eGeneral);
|
||||
set_writes.push_back({
|
||||
.dstSet = VK_NULL_HANDLE,
|
||||
.dstBinding = binding++,
|
||||
.dstBinding = binding.unified++,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampler,
|
||||
|
|
|
@ -264,7 +264,7 @@ bool PipelineCache::RefreshGraphicsKey() {
|
|||
++remapped_cb;
|
||||
}
|
||||
|
||||
u32 binding{};
|
||||
Shader::Backend::Bindings binding{};
|
||||
for (u32 i = 0; i < MaxShaderStages; i++) {
|
||||
if (!regs.stage_enable.IsStageEnabled(i)) {
|
||||
key.stage_hashes[i] = 0;
|
||||
|
@ -332,7 +332,7 @@ bool PipelineCache::RefreshGraphicsKey() {
|
|||
}
|
||||
|
||||
bool PipelineCache::RefreshComputeKey() {
|
||||
u32 binding{};
|
||||
Shader::Backend::Bindings binding{};
|
||||
const auto* cs_pgm = &liverpool->regs.cs_program;
|
||||
const auto cs_params = Liverpool::GetParams(*cs_pgm);
|
||||
if (ShouldSkipShader(cs_params.hash, "compute")) {
|
||||
|
@ -346,7 +346,7 @@ bool PipelineCache::RefreshComputeKey() {
|
|||
vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info,
|
||||
const Shader::RuntimeInfo& runtime_info,
|
||||
std::span<const u32> code, size_t perm_idx,
|
||||
u32& binding) {
|
||||
Shader::Backend::Bindings& binding) {
|
||||
LOG_INFO(Render_Vulkan, "Compiling {} shader {:#x} {}", info.stage, info.pgm_hash,
|
||||
perm_idx != 0 ? "(permutation)" : "");
|
||||
if (Config::dumpShaders()) {
|
||||
|
@ -366,14 +366,14 @@ vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info,
|
|||
}
|
||||
|
||||
std::tuple<const Shader::Info*, vk::ShaderModule, u64> PipelineCache::GetProgram(
|
||||
Shader::Stage stage, Shader::ShaderParams params, u32& binding) {
|
||||
Shader::Stage stage, Shader::ShaderParams params, Shader::Backend::Bindings& binding) {
|
||||
const auto runtime_info = BuildRuntimeInfo(stage);
|
||||
auto [it_pgm, new_program] = program_cache.try_emplace(params.hash);
|
||||
if (new_program) {
|
||||
Program* program = program_pool.Create(stage, params);
|
||||
u32 start_binding = binding;
|
||||
auto start = binding;
|
||||
const auto module = CompileModule(program->info, runtime_info, params.code, 0, binding);
|
||||
const auto spec = Shader::StageSpecialization(program->info, runtime_info, start_binding);
|
||||
const auto spec = Shader::StageSpecialization(program->info, runtime_info, start);
|
||||
program->AddPermut(module, std::move(spec));
|
||||
it_pgm.value() = program;
|
||||
return std::make_tuple(&program->info, module, HashCombine(params.hash, 0));
|
||||
|
@ -391,7 +391,7 @@ std::tuple<const Shader::Info*, vk::ShaderModule, u64> PipelineCache::GetProgram
|
|||
module = CompileModule(new_info, runtime_info, params.code, perm_idx, binding);
|
||||
program->AddPermut(module, std::move(spec));
|
||||
} else {
|
||||
binding += info.NumBindings();
|
||||
info.AddBindings(binding);
|
||||
module = it->module;
|
||||
perm_idx = std::distance(program->modules.begin(), it);
|
||||
}
|
||||
|
|
|
@ -49,9 +49,8 @@ public:
|
|||
|
||||
const ComputePipeline* GetComputePipeline();
|
||||
|
||||
std::tuple<const Shader::Info*, vk::ShaderModule, u64> GetProgram(Shader::Stage stage,
|
||||
Shader::ShaderParams params,
|
||||
u32& binding);
|
||||
std::tuple<const Shader::Info*, vk::ShaderModule, u64> GetProgram(
|
||||
Shader::Stage stage, Shader::ShaderParams params, Shader::Backend::Bindings& binding);
|
||||
|
||||
private:
|
||||
bool RefreshGraphicsKey();
|
||||
|
@ -60,7 +59,8 @@ private:
|
|||
void DumpShader(std::span<const u32> code, u64 hash, Shader::Stage stage, size_t perm_idx,
|
||||
std::string_view ext);
|
||||
vk::ShaderModule CompileModule(Shader::Info& info, const Shader::RuntimeInfo& runtime_info,
|
||||
std::span<const u32> code, size_t perm_idx, u32& binding);
|
||||
std::span<const u32> code, size_t perm_idx,
|
||||
Shader::Backend::Bindings& binding);
|
||||
Shader::RuntimeInfo BuildRuntimeInfo(Shader::Stage stage);
|
||||
|
||||
private:
|
||||
|
|
|
@ -20,7 +20,8 @@ Pipeline::Pipeline(const Instance& instance_, Scheduler& scheduler_, DescriptorH
|
|||
Pipeline::~Pipeline() = default;
|
||||
|
||||
void Pipeline::BindTextures(VideoCore::TextureCache& texture_cache, const Shader::Info& stage,
|
||||
u32& binding, DescriptorWrites& set_writes) const {
|
||||
Shader::Backend::Bindings& binding,
|
||||
DescriptorWrites& set_writes) const {
|
||||
|
||||
using ImageBindingInfo = std::tuple<VideoCore::ImageId, AmdGpu::Image, Shader::ImageResource>;
|
||||
boost::container::static_vector<ImageBindingInfo, 32> image_bindings;
|
||||
|
@ -67,7 +68,7 @@ void Pipeline::BindTextures(VideoCore::TextureCache& texture_cache, const Shader
|
|||
|
||||
set_writes.push_back({
|
||||
.dstSet = VK_NULL_HANDLE,
|
||||
.dstBinding = binding++,
|
||||
.dstBinding = binding.unified++,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = desc.is_storage ? vk::DescriptorType::eStorageImage
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "shader_recompiler/backend/bindings.h"
|
||||
#include "shader_recompiler/info.h"
|
||||
#include "video_core/renderer_vulkan/vk_common.h"
|
||||
|
||||
|
@ -33,7 +34,7 @@ public:
|
|||
|
||||
using DescriptorWrites = boost::container::small_vector<vk::WriteDescriptorSet, 16>;
|
||||
void BindTextures(VideoCore::TextureCache& texture_cache, const Shader::Info& stage,
|
||||
u32& binding, DescriptorWrites& set_writes) const;
|
||||
Shader::Backend::Bindings& binding, DescriptorWrites& set_writes) const;
|
||||
|
||||
protected:
|
||||
const Instance& instance;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue