mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-02 08:43:16 +00:00
video_core: Account of runtime state changes when compiling shaders (#575)
* video_core: Compile shader permutations * spirv: Only specific storage image format for atomics * ir: Avoid cube coord patching for storage image * spirv: Fix default attributes * data_share: Add more instructions * video_core: Query storage flag with runtime state * kernel: Use std::list for semaphore * video_core: Use texture buffers for untyped format load/store * buffer_cache: Limit view usage * vk_pipeline_cache: Fix invalid iterator * image_view: Reduce log spam when alpha=1 in storage swizzle * video_core: More features and proper spirv feature detection * video_core: Attempt no2 for specialization * spirv: Remove conflict * vk_shader_cache: Small cleanup
This commit is contained in:
parent
790d19e59b
commit
66e96dd944
43 changed files with 1058 additions and 976 deletions
|
@ -13,13 +13,6 @@
|
|||
|
||||
namespace VideoCore {
|
||||
|
||||
constexpr vk::BufferUsageFlags AllFlags =
|
||||
vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst |
|
||||
vk::BufferUsageFlagBits::eUniformTexelBuffer | vk::BufferUsageFlagBits::eStorageTexelBuffer |
|
||||
vk::BufferUsageFlagBits::eUniformBuffer | vk::BufferUsageFlagBits::eStorageBuffer |
|
||||
vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eVertexBuffer |
|
||||
vk::BufferUsageFlagBits::eIndirectBuffer;
|
||||
|
||||
std::string_view BufferTypeName(MemoryUsage type) {
|
||||
switch (type) {
|
||||
case MemoryUsage::Upload:
|
||||
|
@ -96,13 +89,13 @@ void UniqueBuffer::Create(const vk::BufferCreateInfo& buffer_ci, MemoryUsage usa
|
|||
}
|
||||
|
||||
Buffer::Buffer(const Vulkan::Instance& instance_, MemoryUsage usage_, VAddr cpu_addr_,
|
||||
u64 size_bytes_)
|
||||
vk::BufferUsageFlags flags, u64 size_bytes_)
|
||||
: cpu_addr{cpu_addr_}, size_bytes{size_bytes_}, instance{&instance_}, usage{usage_},
|
||||
buffer{instance->GetDevice(), instance->GetAllocator()} {
|
||||
// Create buffer object.
|
||||
const vk::BufferCreateInfo buffer_ci = {
|
||||
.size = size_bytes,
|
||||
.usage = AllFlags,
|
||||
.usage = flags,
|
||||
};
|
||||
VmaAllocationInfo alloc_info{};
|
||||
buffer.Create(buffer_ci, usage, &alloc_info);
|
||||
|
@ -119,25 +112,33 @@ Buffer::Buffer(const Vulkan::Instance& instance_, MemoryUsage usage_, VAddr cpu_
|
|||
is_coherent = property_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
||||
}
|
||||
|
||||
vk::BufferView Buffer::View(u32 offset, u32 size, AmdGpu::DataFormat dfmt,
|
||||
vk::BufferView Buffer::View(u32 offset, u32 size, bool is_written, AmdGpu::DataFormat dfmt,
|
||||
AmdGpu::NumberFormat nfmt) {
|
||||
const auto it{std::ranges::find_if(views, [offset, size, dfmt, nfmt](const BufferView& view) {
|
||||
return offset == view.offset && size == view.size && dfmt == view.dfmt && nfmt == view.nfmt;
|
||||
const auto it{std::ranges::find_if(views, [=](const BufferView& view) {
|
||||
return offset == view.offset && size == view.size && is_written == view.is_written &&
|
||||
dfmt == view.dfmt && nfmt == view.nfmt;
|
||||
})};
|
||||
if (it != views.end()) {
|
||||
return it->handle;
|
||||
}
|
||||
const vk::BufferUsageFlags2CreateInfoKHR usage_flags = {
|
||||
.usage = is_written ? vk::BufferUsageFlagBits2KHR::eStorageTexelBuffer
|
||||
: vk::BufferUsageFlagBits2KHR::eUniformTexelBuffer,
|
||||
};
|
||||
const vk::BufferViewCreateInfo view_ci = {
|
||||
.pNext = &usage_flags,
|
||||
.buffer = buffer.buffer,
|
||||
.format = Vulkan::LiverpoolToVK::SurfaceFormat(dfmt, nfmt),
|
||||
.offset = offset,
|
||||
.range = size,
|
||||
};
|
||||
views.push_back({
|
||||
.offset = offset,
|
||||
.size = size,
|
||||
.is_written = is_written,
|
||||
.dfmt = dfmt,
|
||||
.nfmt = nfmt,
|
||||
.handle = instance->GetDevice().createBufferView({
|
||||
.buffer = buffer.buffer,
|
||||
.format = Vulkan::LiverpoolToVK::SurfaceFormat(dfmt, nfmt),
|
||||
.offset = offset,
|
||||
.range = size,
|
||||
}),
|
||||
.handle = instance->GetDevice().createBufferView(view_ci),
|
||||
});
|
||||
return views.back().handle;
|
||||
}
|
||||
|
@ -147,7 +148,7 @@ constexpr u64 WATCHES_RESERVE_CHUNK = 0x1000;
|
|||
|
||||
StreamBuffer::StreamBuffer(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler_,
|
||||
MemoryUsage usage, u64 size_bytes)
|
||||
: Buffer{instance, usage, 0, size_bytes}, scheduler{scheduler_} {
|
||||
: Buffer{instance, usage, 0, AllFlags, size_bytes}, scheduler{scheduler_} {
|
||||
ReserveWatches(current_watches, WATCHES_INITIAL_RESERVE);
|
||||
ReserveWatches(previous_watches, WATCHES_INITIAL_RESERVE);
|
||||
const auto device = instance.GetDevice();
|
||||
|
|
|
@ -31,6 +31,15 @@ enum class MemoryUsage {
|
|||
Stream, ///< Requests device local host visible buffer, falling back host memory.
|
||||
};
|
||||
|
||||
constexpr vk::BufferUsageFlags ReadFlags =
|
||||
vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eUniformTexelBuffer |
|
||||
vk::BufferUsageFlagBits::eUniformBuffer | vk::BufferUsageFlagBits::eIndexBuffer |
|
||||
vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eIndirectBuffer;
|
||||
|
||||
constexpr vk::BufferUsageFlags AllFlags = ReadFlags | vk::BufferUsageFlagBits::eTransferDst |
|
||||
vk::BufferUsageFlagBits::eStorageTexelBuffer |
|
||||
vk::BufferUsageFlagBits::eStorageBuffer;
|
||||
|
||||
struct UniqueBuffer {
|
||||
explicit UniqueBuffer(vk::Device device, VmaAllocator allocator);
|
||||
~UniqueBuffer();
|
||||
|
@ -65,7 +74,7 @@ struct UniqueBuffer {
|
|||
class Buffer {
|
||||
public:
|
||||
explicit Buffer(const Vulkan::Instance& instance, MemoryUsage usage, VAddr cpu_addr_,
|
||||
u64 size_bytes_);
|
||||
vk::BufferUsageFlags flags, u64 size_bytes_);
|
||||
|
||||
Buffer& operator=(const Buffer&) = delete;
|
||||
Buffer(const Buffer&) = delete;
|
||||
|
@ -73,7 +82,8 @@ public:
|
|||
Buffer& operator=(Buffer&&) = default;
|
||||
Buffer(Buffer&&) = default;
|
||||
|
||||
vk::BufferView View(u32 offset, u32 size, AmdGpu::DataFormat dfmt, AmdGpu::NumberFormat nfmt);
|
||||
vk::BufferView View(u32 offset, u32 size, bool is_written, AmdGpu::DataFormat dfmt,
|
||||
AmdGpu::NumberFormat nfmt);
|
||||
|
||||
/// Increases the likeliness of this being a stream buffer
|
||||
void IncreaseStreamScore(int score) noexcept {
|
||||
|
@ -121,6 +131,7 @@ public:
|
|||
struct BufferView {
|
||||
u32 offset;
|
||||
u32 size;
|
||||
bool is_written;
|
||||
AmdGpu::DataFormat dfmt;
|
||||
AmdGpu::NumberFormat nfmt;
|
||||
vk::BufferView handle;
|
||||
|
|
|
@ -23,7 +23,7 @@ BufferCache::BufferCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& s
|
|||
stream_buffer{instance, scheduler, MemoryUsage::Stream, UboStreamBufferSize},
|
||||
memory_tracker{&tracker} {
|
||||
// Ensure the first slot is used for the null buffer
|
||||
void(slot_buffers.insert(instance, MemoryUsage::DeviceLocal, 0, 1));
|
||||
void(slot_buffers.insert(instance, MemoryUsage::DeviceLocal, 0, ReadFlags, 1));
|
||||
}
|
||||
|
||||
BufferCache::~BufferCache() = default;
|
||||
|
@ -421,7 +421,7 @@ BufferId BufferCache::CreateBuffer(VAddr device_addr, u32 wanted_size) {
|
|||
const OverlapResult overlap = ResolveOverlaps(device_addr, wanted_size);
|
||||
const u32 size = static_cast<u32>(overlap.end - overlap.begin);
|
||||
const BufferId new_buffer_id =
|
||||
slot_buffers.insert(instance, MemoryUsage::DeviceLocal, overlap.begin, size);
|
||||
slot_buffers.insert(instance, MemoryUsage::DeviceLocal, overlap.begin, AllFlags, size);
|
||||
auto& new_buffer = slot_buffers[new_buffer_id];
|
||||
const size_t size_bytes = new_buffer.SizeBytes();
|
||||
const auto cmdbuf = scheduler.CommandBuffer();
|
||||
|
@ -495,7 +495,8 @@ bool BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size)
|
|||
} else {
|
||||
// For large one time transfers use a temporary host buffer.
|
||||
// RenderDoc can lag quite a bit if the stream buffer is too large.
|
||||
Buffer temp_buffer{instance, MemoryUsage::Upload, 0, total_size_bytes};
|
||||
Buffer temp_buffer{instance, MemoryUsage::Upload, 0, vk::BufferUsageFlagBits::eTransferSrc,
|
||||
total_size_bytes};
|
||||
src_buffer = temp_buffer.Handle();
|
||||
u8* const staging = temp_buffer.mapped_data.data();
|
||||
for (auto& copy : copies) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue