Compare commits

..

23 Commits

Author SHA1 Message Date
CamilleLaVey f199597158 [TEST] DR Off 2026-07-17 21:03:17 -04:00
CamilleLaVey 9c313fb787 [TEST] Caching for texture + pages on NCE 2026-07-17 20:15:19 -04:00
CamilleLaVey eec29b83f3 [TEST] Coalesce NCE fault write. 2026-07-17 19:56:16 -04:00
CamilleLaVey a57041d62f [TEST] Discards on MSAA depth/stencil 2026-07-17 17:57:55 -04:00
CamilleLaVey 4956bc86c3 [TEST] Hunting down recursive mutex 7 2026-07-17 17:44:24 -04:00
CamilleLaVey e8b1dc7c0b [TEST] Adjustments on CommandPools + ResetQueryPool 2026-07-17 07:52:45 -04:00
CamilleLaVey e81d170458 [TEST] Remove unnecessary memory upload 2026-07-17 07:28:30 -04:00
CamilleLaVey 7ed7e5e31d [TEST] Remove unnecessary submit 2026-07-17 03:56:02 -04:00
CamilleLaVey eb32b8766a [TEST] Hunting down recursive mutex 6 2026-07-17 03:13:55 -04:00
CamilleLaVey a484e6c34b [TEST] Hunting down recursive mutex 5 2026-07-17 03:00:53 -04:00
CamilleLaVey 84490a7d6f [TEST] Hunting down recursive mutex 4 2026-07-17 02:32:14 -04:00
CamilleLaVey 933f79af95 [TEST] Hunting down recursive mutex 3 2026-07-17 02:15:10 -04:00
CamilleLaVey f532357793 [TEST] Hunting down recursive mutex 2 2026-07-17 01:55:28 -04:00
CamilleLaVey ab92e5fa52 [TEST] Hunting down recursive mutex 1 2026-07-17 01:13:15 -04:00
CamilleLaVey 791880f9bf [TEST] Adjust records/commandBuffer 2026-07-16 22:50:08 -04:00
CamilleLaVey e058a15074 [TEST] Wire MSAA resolve to dynamic rendering native resolve 2026-07-16 20:29:18 -04:00
CamilleLaVey 6313800aee [TEST] Check on color components for masks/blending 2026-07-16 20:02:59 -04:00
CamilleLaVey 5428dbbd14 [TEST] Adjustments on blit/clears per blending object 2026-07-16 17:04:32 -04:00
CamilleLaVey 9694216ad7 [TEST] 2nd stage on dynamic rendering implementation 2026-07-16 16:53:22 -04:00
CamilleLaVey 4fbdc133dd [vulkan] Add resume/supend bits on renderpass 2026-07-16 15:50:36 -04:00
CamilleLaVey f210f16e8c [TEST] Debug on clears made by driver 2026-07-16 15:47:23 -04:00
CamilleLaVey 20bf6bc282 [vulkan] Adjustment on the framebuffer use vs non used attachments 2026-07-16 15:45:49 -04:00
CamilleLaVey 99e95eebb1 [vulkan] Initial dynamic rendering implementation 2026-07-16 15:44:06 -04:00
23 changed files with 634 additions and 2188 deletions
@@ -121,15 +121,6 @@ void BufferCache<P>::WriteMemory(DAddr device_addr, u64 size) {
memory_tracker.MarkRegionAsCpuModified(device_addr, size); memory_tracker.MarkRegionAsCpuModified(device_addr, size);
} }
template <class P>
void BufferCache<P>::CpuWriteInvalidate(DAddr device_addr, u64 size) {
if (!memory_tracker.CpuMarkIfNotGpuModified(device_addr, size)) {
return;
}
std::scoped_lock lock{mutex};
WriteMemory(device_addr, size);
}
template <class P> template <class P>
void BufferCache<P>::CachedWriteMemory(DAddr device_addr, u64 size) { void BufferCache<P>::CachedWriteMemory(DAddr device_addr, u64 size) {
const bool is_dirty = IsRegionRegistered(device_addr, size); const bool is_dirty = IsRegionRegistered(device_addr, size);
@@ -1721,9 +1712,6 @@ void BufferCache<P>::TouchBuffer(Buffer& buffer, BufferId buffer_id) noexcept {
template <class P> template <class P>
bool BufferCache<P>::SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 size) { bool BufferCache<P>::SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 size) {
if (!memory_tracker.HasCpuModifiedCheap(device_addr, size)) {
return true;
}
upload_copies.clear(); upload_copies.clear();
u64 total_size_bytes = 0; u64 total_size_bytes = 0;
u64 largest_copy = 0; u64 largest_copy = 0;
@@ -217,8 +217,6 @@ public:
void WriteMemory(DAddr device_addr, u64 size); void WriteMemory(DAddr device_addr, u64 size);
void CpuWriteInvalidate(DAddr device_addr, u64 size);
void CachedWriteMemory(DAddr device_addr, u64 size); void CachedWriteMemory(DAddr device_addr, u64 size);
bool OnCPUWrite(DAddr device_addr, u64 size); bool OnCPUWrite(DAddr device_addr, u64 size);
@@ -7,11 +7,9 @@
#pragma once #pragma once
#include <algorithm> #include <algorithm>
#include <atomic>
#include <bit> #include <bit>
#include <deque> #include <deque>
#include <limits> #include <limits>
#include <mutex>
#include <type_traits> #include <type_traits>
#include <ankerl/unordered_dense.h> #include <ankerl/unordered_dense.h>
#include <utility> #include <utility>
@@ -51,24 +49,6 @@ public:
}); });
} }
[[nodiscard]] bool HasCpuModifiedCheap(VAddr query_cpu_addr, u64 query_size) noexcept {
std::size_t remaining_size{query_size};
std::size_t page_index{query_cpu_addr >> HIGHER_PAGE_BITS};
u64 page_offset{query_cpu_addr & HIGHER_PAGE_MASK};
while (remaining_size > 0) {
const std::size_t copy_amount{
std::min<std::size_t>(HIGHER_PAGE_SIZE - page_offset, remaining_size)};
const Manager* manager = top_tier[page_index].load(std::memory_order_acquire);
if (manager == nullptr || manager->CpuModifiedPageCount() != 0) {
return true;
}
page_index++;
page_offset = 0;
remaining_size -= copy_amount;
}
return false;
}
/// Returns true if a region has been modified from the CPU /// Returns true if a region has been modified from the CPU
[[nodiscard]] bool IsRegionCpuModified(VAddr query_cpu_addr, u64 query_size) noexcept { [[nodiscard]] bool IsRegionCpuModified(VAddr query_cpu_addr, u64 query_size) noexcept {
return IteratePages<true>(query_cpu_addr, query_size, [](Manager* manager, u64 offset, size_t size) { return IteratePages<true>(query_cpu_addr, query_size, [](Manager* manager, u64 offset, size_t size) {
@@ -150,28 +130,12 @@ public:
} }
void FlushCachedWrites() noexcept { void FlushCachedWrites() noexcept {
std::scoped_lock lk{tracker_mutex};
for (auto id : cached_pages) { for (auto id : cached_pages) {
top_tier[id].load(std::memory_order_relaxed)->FlushCachedWrites(); top_tier[id]->FlushCachedWrites();
} }
cached_pages.clear(); cached_pages.clear();
} }
[[nodiscard]] bool CpuMarkIfNotGpuModified(VAddr addr, u64 size) {
std::scoped_lock lk{tracker_mutex};
const bool gpu = IteratePagesNoLock<false>(
addr, size, [](Manager* manager, u64 offset, size_t sz) {
return manager->IsRegionModified(Type::GPU, offset, sz);
});
if (gpu) {
return true;
}
IteratePagesNoLock<true>(addr, size, [](Manager* manager, u64 offset, size_t sz) {
manager->ChangeRegionState(Type::CPU, true, manager->cpu_addr + offset, sz);
});
return false;
}
/// Call 'func' for each CPU modified range and unmark those pages as CPU modified /// Call 'func' for each CPU modified range and unmark those pages as CPU modified
template <typename Func> template <typename Func>
void ForEachUploadRange(VAddr query_cpu_range, u64 query_size, Func&& func) { void ForEachUploadRange(VAddr query_cpu_range, u64 query_size, Func&& func) {
@@ -198,12 +162,6 @@ public:
private: private:
template <bool create_region_on_fail, typename Func> template <bool create_region_on_fail, typename Func>
bool IteratePages(VAddr cpu_address, size_t size, Func&& func) { bool IteratePages(VAddr cpu_address, size_t size, Func&& func) {
std::scoped_lock lk{tracker_mutex};
return IteratePagesNoLock<create_region_on_fail>(cpu_address, size, std::forward<Func>(func));
}
template <bool create_region_on_fail, typename Func>
bool IteratePagesNoLock(VAddr cpu_address, size_t size, Func&& func) {
using FuncReturn = typename std::invoke_result<Func, Manager*, u64, size_t>::type; using FuncReturn = typename std::invoke_result<Func, Manager*, u64, size_t>::type;
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>; static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
std::size_t remaining_size{size}; std::size_t remaining_size{size};
@@ -212,7 +170,7 @@ private:
while (remaining_size > 0) { while (remaining_size > 0) {
const std::size_t copy_amount{ const std::size_t copy_amount{
std::min<std::size_t>(HIGHER_PAGE_SIZE - page_offset, remaining_size)}; std::min<std::size_t>(HIGHER_PAGE_SIZE - page_offset, remaining_size)};
auto* manager{top_tier[page_index].load(std::memory_order_relaxed)}; auto* manager{top_tier[page_index]};
if (manager) { if (manager) {
if constexpr (BOOL_BREAK) { if constexpr (BOOL_BREAK) {
if (func(manager, page_offset, copy_amount)) { if (func(manager, page_offset, copy_amount)) {
@@ -223,7 +181,7 @@ private:
} }
} else if constexpr (create_region_on_fail) { } else if constexpr (create_region_on_fail) {
CreateRegion(page_index); CreateRegion(page_index);
manager = top_tier[page_index].load(std::memory_order_relaxed); manager = top_tier[page_index];
if constexpr (BOOL_BREAK) { if constexpr (BOOL_BREAK) {
if (func(manager, page_offset, copy_amount)) { if (func(manager, page_offset, copy_amount)) {
return true; return true;
@@ -241,7 +199,6 @@ private:
template <bool create_region_on_fail, typename Func> template <bool create_region_on_fail, typename Func>
std::pair<u64, u64> IteratePairs(VAddr cpu_address, size_t size, Func&& func) { std::pair<u64, u64> IteratePairs(VAddr cpu_address, size_t size, Func&& func) {
std::scoped_lock lk{tracker_mutex};
std::size_t remaining_size{size}; std::size_t remaining_size{size};
std::size_t page_index{cpu_address >> HIGHER_PAGE_BITS}; std::size_t page_index{cpu_address >> HIGHER_PAGE_BITS};
u64 page_offset{cpu_address & HIGHER_PAGE_MASK}; u64 page_offset{cpu_address & HIGHER_PAGE_MASK};
@@ -250,7 +207,7 @@ private:
while (remaining_size > 0) { while (remaining_size > 0) {
const std::size_t copy_amount{ const std::size_t copy_amount{
std::min<std::size_t>(HIGHER_PAGE_SIZE - page_offset, remaining_size)}; std::min<std::size_t>(HIGHER_PAGE_SIZE - page_offset, remaining_size)};
auto* manager{top_tier[page_index].load(std::memory_order_relaxed)}; auto* manager{top_tier[page_index]};
const auto execute = [&] { const auto execute = [&] {
auto [new_begin, new_end] = func(manager, page_offset, copy_amount); auto [new_begin, new_end] = func(manager, page_offset, copy_amount);
if (new_begin != 0 || new_end != 0) { if (new_begin != 0 || new_end != 0) {
@@ -263,7 +220,7 @@ private:
execute(); execute();
} else if constexpr (create_region_on_fail) { } else if constexpr (create_region_on_fail) {
CreateRegion(page_index); CreateRegion(page_index);
manager = top_tier[page_index].load(std::memory_order_relaxed); manager = top_tier[page_index];
execute(); execute();
} }
page_index++; page_index++;
@@ -279,7 +236,7 @@ private:
void CreateRegion(std::size_t page_index) { void CreateRegion(std::size_t page_index) {
const VAddr base_cpu_addr = page_index << HIGHER_PAGE_BITS; const VAddr base_cpu_addr = page_index << HIGHER_PAGE_BITS;
top_tier[page_index].store(GetNewManager(base_cpu_addr), std::memory_order_release); top_tier[page_index] = GetNewManager(base_cpu_addr);
} }
Manager* GetNewManager(VAddr base_cpu_address) { Manager* GetNewManager(VAddr base_cpu_address) {
@@ -297,12 +254,11 @@ private:
return new_manager; return new_manager;
} }
std::array<std::atomic<Manager*>, NUM_HIGH_PAGES> top_tier{}; std::array<Manager*, NUM_HIGH_PAGES> top_tier{};
std::deque<std::array<Manager, MANAGER_POOL_SIZE>> manager_pool; std::deque<std::array<Manager, MANAGER_POOL_SIZE>> manager_pool;
std::deque<Manager*> free_managers; std::deque<Manager*> free_managers;
ankerl::unordered_dense::set<u32> cached_pages; ankerl::unordered_dense::set<u32> cached_pages;
DeviceTracker* device_tracker = nullptr; DeviceTracker* device_tracker = nullptr;
std::mutex tracker_mutex;
}; };
} // namespace VideoCommon } // namespace VideoCommon
@@ -7,7 +7,6 @@
#pragma once #pragma once
#include <algorithm> #include <algorithm>
#include <atomic>
#include <bit> #include <bit>
#include <limits> #include <limits>
#include <span> #include <span>
@@ -49,11 +48,6 @@ struct WordManager {
u64 const last_word = (~u64{0} << shift) >> shift; u64 const last_word = (~u64{0} << shift) >> shift;
heap[num_words * size_t(Type::CPU) + num_words - 1] = last_word; heap[num_words * size_t(Type::CPU) + num_words - 1] = last_word;
heap[num_words * size_t(Type::Untracked) + num_words - 1] = last_word; heap[num_words * size_t(Type::Untracked) + num_words - 1] = last_word;
u32 cpu_pages = 0;
for (size_t i = 0; i < num_words; ++i) {
cpu_pages += static_cast<u32>(std::popcount(heap[num_words * size_t(Type::CPU) + i]));
}
cpu_modified_pages.store(cpu_pages, std::memory_order_relaxed);
} }
explicit WordManager() = default; explicit WordManager() = default;
@@ -126,15 +120,10 @@ struct WordManager {
[[maybe_unused]] std::span<u64> untracked_words = Span(Type::Untracked); [[maybe_unused]] std::span<u64> untracked_words = Span(Type::Untracked);
[[maybe_unused]] std::span<u64> cached_words = Span(Type::CachedCPU); [[maybe_unused]] std::span<u64> cached_words = Span(Type::CachedCPU);
std::vector<std::pair<VAddr, u64>> ranges; std::vector<std::pair<VAddr, u64>> ranges;
s64 cpu_delta = 0;
IterateWords(dirty_addr - cpu_addr, size, [&](size_t index, u64 mask) { IterateWords(dirty_addr - cpu_addr, size, [&](size_t index, u64 mask) {
if (type == Type::CPU || type == Type::CachedCPU) { if (type == Type::CPU || type == Type::CachedCPU) {
CollectChangedRanges(!enable, index, untracked_words[index], mask, ranges); CollectChangedRanges(!enable, index, untracked_words[index], mask, ranges);
} }
if (type == Type::CPU) {
const u64 old = state_words[index];
cpu_delta += enable ? std::popcount(~old & mask) : -std::popcount(old & mask);
}
if (enable) { if (enable) {
state_words[index] |= mask; state_words[index] |= mask;
if (type == Type::CPU || type == Type::CachedCPU) if (type == Type::CPU || type == Type::CachedCPU)
@@ -149,9 +138,6 @@ struct WordManager {
untracked_words[index] &= ~mask; untracked_words[index] &= ~mask;
} }
}); });
if (cpu_delta != 0) {
cpu_modified_pages.fetch_add(static_cast<u32>(cpu_delta), std::memory_order_release);
}
if (!ranges.empty()) { if (!ranges.empty()) {
ApplyCollectedRanges(ranges, (!enable) ? 1 : -1); ApplyCollectedRanges(ranges, (!enable) ? 1 : -1);
} }
@@ -179,7 +165,6 @@ struct WordManager {
(pending_pointer - pending_offset) * BYTES_PER_PAGE); (pending_pointer - pending_offset) * BYTES_PER_PAGE);
}; };
std::vector<std::pair<VAddr, u64>> ranges; std::vector<std::pair<VAddr, u64>> ranges;
s64 cpu_delta = 0;
IterateWords(offset, size, [&](size_t index, u64 mask) { IterateWords(offset, size, [&](size_t index, u64 mask) {
if (type == Type::GPU) if (type == Type::GPU)
mask &= ~untracked_words[index]; mask &= ~untracked_words[index];
@@ -188,8 +173,6 @@ struct WordManager {
if (type == Type::CPU || type == Type::CachedCPU) { if (type == Type::CPU || type == Type::CachedCPU) {
CollectChangedRanges(true, index, untracked_words[index], mask, ranges); CollectChangedRanges(true, index, untracked_words[index], mask, ranges);
} }
if (type == Type::CPU)
cpu_delta -= std::popcount(word);
state_words[index] &= ~mask; state_words[index] &= ~mask;
if (type == Type::CPU || type == Type::CachedCPU) if (type == Type::CPU || type == Type::CachedCPU)
untracked_words[index] &= ~mask; untracked_words[index] &= ~mask;
@@ -211,9 +194,6 @@ struct WordManager {
} }
}); });
}); });
if (cpu_delta != 0) {
cpu_modified_pages.fetch_add(static_cast<u32>(cpu_delta), std::memory_order_release);
}
if (pending) { if (pending) {
release(); release();
} }
@@ -268,18 +248,13 @@ struct WordManager {
auto const untracked_words = Span(Type::Untracked); auto const untracked_words = Span(Type::Untracked);
auto const cpu_words = Span(Type::CPU); auto const cpu_words = Span(Type::CPU);
std::vector<std::pair<VAddr, u64>> ranges; std::vector<std::pair<VAddr, u64>> ranges;
s64 cpu_delta = 0;
for (u64 word_index = 0; word_index < num_words; ++word_index) { for (u64 word_index = 0; word_index < num_words; ++word_index) {
const u64 cached_bits = cached_words[word_index]; const u64 cached_bits = cached_words[word_index];
CollectChangedRanges(false, word_index, untracked_words[word_index], cached_bits, ranges); CollectChangedRanges(false, word_index, untracked_words[word_index], cached_bits, ranges);
cpu_delta += std::popcount(~cpu_words[word_index] & cached_bits);
untracked_words[word_index] |= cached_bits; untracked_words[word_index] |= cached_bits;
cpu_words[word_index] |= cached_bits; cpu_words[word_index] |= cached_bits;
cached_words[word_index] = 0; cached_words[word_index] = 0;
} }
if (cpu_delta != 0) {
cpu_modified_pages.fetch_add(static_cast<u32>(cpu_delta), std::memory_order_release);
}
if (!ranges.empty()) { if (!ranges.empty()) {
ApplyCollectedRanges(ranges, -1); ApplyCollectedRanges(ranges, -1);
} }
@@ -344,14 +319,9 @@ struct WordManager {
return std::span<const u64>(heap.data() + num_words * size_t(type), num_words); return std::span<const u64>(heap.data() + num_words * size_t(type), num_words);
} }
[[nodiscard]] u32 CpuModifiedPageCount() const noexcept {
return cpu_modified_pages.load(std::memory_order_acquire);
}
std::array<u64, size_t(Type::Max) * num_words> heap = {}; std::array<u64, size_t(Type::Max) * num_words> heap = {};
DeviceTracker* tracker = nullptr; DeviceTracker* tracker = nullptr;
VAddr cpu_addr = 0; VAddr cpu_addr = 0;
std::atomic<u32> cpu_modified_pages{0};
}; };
} // namespace VideoCommon } // namespace VideoCommon
@@ -15,8 +15,6 @@ set(GLSL_INCLUDES
set(SHADER_FILES set(SHADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/astc_decoder.comp ${CMAKE_CURRENT_SOURCE_DIR}/astc_decoder.comp
${CMAKE_CURRENT_SOURCE_DIR}/astc_decoder.frag
${CMAKE_CURRENT_SOURCE_DIR}/astc_decoder.vert
${CMAKE_CURRENT_SOURCE_DIR}/blit_color_float.frag ${CMAKE_CURRENT_SOURCE_DIR}/blit_color_float.frag
${CMAKE_CURRENT_SOURCE_DIR}/block_linear_unswizzle_2d.comp ${CMAKE_CURRENT_SOURCE_DIR}/block_linear_unswizzle_2d.comp
${CMAKE_CURRENT_SOURCE_DIR}/blit_color_msaa.frag ${CMAKE_CURRENT_SOURCE_DIR}/blit_color_msaa.frag
+31 -65
View File
@@ -964,70 +964,35 @@ void ComputeEndpoints(out uvec4 ep1, out uvec4 ep2, uint color_endpoint_mode, ui
} }
uint UnquantizeTexelWeight(EncodingData val) { uint UnquantizeTexelWeight(EncodingData val) {
const uint encoding = Encoding(val); uint encoding = Encoding(val), bitlen = NumBits(val), bitval = BitValue(val);
const uint bitlen = NumBits(val); if (encoding == JUST_BITS) {
const uint bitval = BitValue(val); return (bitlen >= 1 && bitlen <= 5)
const uint A = ReplicateBitTo7((bitval & 1)); ? uint(floor(0.5f + float(bitval) * 64.0f / float((1 << bitlen) - 1)))
uint B = 0, C = 0, D = 0; : FastReplicateTo6(bitval, bitlen);
uint result = 0; } else if (encoding == TRIT || encoding == QUINT) {
const uint bitlen_0_results[5] = {0, 16, 32, 48, 64}; uint B = 0, C = 0, D = 0;
switch (encoding) { uint b_mask = (0x3100 >> (bitlen * 4)) & 0xf;
case JUST_BITS: uint b = (bitval >> 1) & b_mask;
return FastReplicateTo6(bitval, bitlen);
case TRIT: {
D = QuintTritValue(val); D = QuintTritValue(val);
switch (bitlen) { if (encoding == TRIT) {
case 0: switch (bitlen) {
return bitlen_0_results[D * 2]; case 0: return D * 32; //0,32,64
case 1: { case 1: C = 50; break;
C = 50; case 2: C = 23; B = (b << 6) | (b << 2) | b; break;
break; case 3: C = 11; B = (b << 5) | b; break;
}
} else if (encoding == QUINT) {
switch (bitlen) {
case 0: return D * 16; //0, 16, 32, 48, 64
case 1: C = 28; break;
case 2: C = 13; B = (b << 6) | (b << 1); break;
}
} }
case 2: { uint A = ReplicateBitTo7(bitval & 1);
C = 23; uint res = (A & 0x20) | (((D * C + B) ^ A) >> 2);
const uint b = (bitval >> 1) & 1; return res + (res > 32 ? 1 : 0);
B = (b << 6) | (b << 2) | b;
break;
}
case 3: {
C = 11;
const uint cb = (bitval >> 1) & 3;
B = (cb << 5) | cb;
break;
}
default:
break;
}
break;
} }
case QUINT: { return 0;
D = QuintTritValue(val);
switch (bitlen) {
case 0:
return bitlen_0_results[D];
case 1: {
C = 28;
break;
}
case 2: {
C = 13;
const uint b = (bitval >> 1) & 1;
B = (b << 6) | (b << 1);
break;
}
}
break;
}
}
if (encoding != JUST_BITS && bitlen > 0) {
result = D * C + B;
result ^= A;
result = (A & 0x20) | (result >> 2);
}
if (result > 32) {
result += 1;
}
return result;
} }
void UnquantizeTexelWeights(uvec2 size, bool is_dual_plane) { void UnquantizeTexelWeights(uvec2 size, bool is_dual_plane) {
@@ -1429,10 +1394,11 @@ void DecompressBlock(ivec3 coord) {
} }
uint SwizzleOffset(uvec2 pos) { uint SwizzleOffset(uvec2 pos) {
const uint x = pos.x; return ((pos.x & 32u) << 3u) |
const uint y = pos.y; ((pos.y & 6u) << 5u) |
return ((x % 64) / 32) * 256 + ((y % 8) / 2) * 64 + ((pos.x & 16u) << 1u) |
((x % 32) / 16) * 32 + (y % 2) * 16 + (x % 16); ((pos.y & 1u) << 4u) |
(pos.x & 15u);
} }
void main() { void main() {
File diff suppressed because it is too large Load Diff
@@ -1,19 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#version 450
#ifdef VULKAN
#define VERTEX_ID gl_VertexIndex
#else
#define VERTEX_ID gl_VertexID
out gl_PerVertex {
vec4 gl_Position;
};
#endif
void main() {
float x = float((VERTEX_ID & 1) << 2);
float y = float((VERTEX_ID & 2) << 1);
gl_Position = vec4(x - 1.0, y - 1.0, 0.0, 1.0);
}
+140 -58
View File
@@ -545,6 +545,10 @@ void RecordShaderReadBarrier(Scheduler& scheduler, const ImageView& image_view)
void BeginRenderPass(vk::CommandBuffer& cmdbuf, const Framebuffer* framebuffer) { void BeginRenderPass(vk::CommandBuffer& cmdbuf, const Framebuffer* framebuffer) {
const VkRenderPass render_pass = framebuffer->RenderPass(); const VkRenderPass render_pass = framebuffer->RenderPass();
if (!render_pass) {
framebuffer->BeginRendering(cmdbuf);
return;
}
const VkFramebuffer framebuffer_handle = framebuffer->Handle(); const VkFramebuffer framebuffer_handle = framebuffer->Handle();
const VkExtent2D render_area = framebuffer->RenderArea(); const VkExtent2D render_area = framebuffer->RenderArea();
const VkRenderPassBeginInfo renderpass_bi{ const VkRenderPassBeginInfo renderpass_bi{
@@ -561,6 +565,31 @@ void BeginRenderPass(vk::CommandBuffer& cmdbuf, const Framebuffer* framebuffer)
}; };
cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE); cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
} }
void EndRenderPass(vk::CommandBuffer& cmdbuf, const Framebuffer* framebuffer) {
if (framebuffer->RenderPass()) {
cmdbuf.EndRenderPass();
} else {
cmdbuf.EndRendering();
}
}
[[nodiscard]] VkPipelineRenderingCreateInfo MakePipelineRenderingCreateInfo(
const Framebuffer* framebuffer) {
return VkPipelineRenderingCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
.pNext = nullptr,
.viewMask = 0,
.colorAttachmentCount = framebuffer->NumColorAttachments(),
.pColorAttachmentFormats = framebuffer->ColorAttachmentFormats().data(),
.depthAttachmentFormat = framebuffer->HasAspectDepthBit()
? framebuffer->DepthAttachmentFormat()
: VK_FORMAT_UNDEFINED,
.stencilAttachmentFormat = framebuffer->HasAspectStencilBit()
? framebuffer->DepthAttachmentFormat()
: VK_FORMAT_UNDEFINED,
};
}
} // Anonymous namespace } // Anonymous namespace
BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_, BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_,
@@ -623,10 +652,12 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageV
const BlitImagePipelineKey key{ const BlitImagePipelineKey key{
.renderpass = dst_framebuffer->RenderPass(), .renderpass = dst_framebuffer->RenderPass(),
.operation = operation, .operation = operation,
.color_formats = dst_framebuffer->ColorAttachmentFormats(),
.depth_format = dst_framebuffer->DepthAttachmentFormat(),
}; };
const VkPipelineLayout layout = *one_texture_pipeline_layout; const VkPipelineLayout layout = *one_texture_pipeline_layout;
const VkSampler sampler = is_linear ? *linear_sampler : *nearest_sampler; const VkSampler sampler = is_linear ? *linear_sampler : *nearest_sampler;
const VkPipeline pipeline = FindOrEmplaceColorPipeline(key); const VkPipeline pipeline = FindOrEmplaceColorPipeline(key, dst_framebuffer);
const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D); const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D);
RecordShaderReadBarrier(scheduler, src_image_view); RecordShaderReadBarrier(scheduler, src_image_view);
@@ -651,9 +682,11 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView
const BlitImagePipelineKey key{ const BlitImagePipelineKey key{
.renderpass = dst_framebuffer->RenderPass(), .renderpass = dst_framebuffer->RenderPass(),
.operation = Tegra::Engines::Fermi2D::Operation::SrcCopy, .operation = Tegra::Engines::Fermi2D::Operation::SrcCopy,
.color_formats = dst_framebuffer->ColorAttachmentFormats(),
.depth_format = dst_framebuffer->DepthAttachmentFormat(),
}; };
const VkPipelineLayout layout = *one_texture_pipeline_layout; const VkPipelineLayout layout = *one_texture_pipeline_layout;
const VkPipeline pipeline = FindOrEmplaceColorPipeline(key); const VkPipeline pipeline = FindOrEmplaceColorPipeline(key, dst_framebuffer);
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([this, dst_framebuffer, src_image_view, src_image, src_sampler, dst_region, scheduler.Record([this, dst_framebuffer, src_image_view, src_image, src_sampler, dst_region,
src_region, src_size, pipeline, layout](vk::CommandBuffer cmdbuf) { src_region, src_size, pipeline, layout](vk::CommandBuffer cmdbuf) {
@@ -666,7 +699,7 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView
nullptr); nullptr);
BindBlitState(cmdbuf, layout, dst_region, src_region, src_size); BindBlitState(cmdbuf, layout, dst_region, src_region, src_size);
cmdbuf.Draw(3, 1, 0, 0); cmdbuf.Draw(3, 1, 0, 0);
cmdbuf.EndRenderPass(); EndRenderPass(cmdbuf, dst_framebuffer);
}); });
} }
@@ -676,10 +709,12 @@ void BlitImageHelper::BlitColorMSAA(const Framebuffer* dst_framebuffer,
const BlitMSAAPipelineKey key{ const BlitMSAAPipelineKey key{
.renderpass = dst_framebuffer->RenderPass(), .renderpass = dst_framebuffer->RenderPass(),
.samples = dst_framebuffer->Samples(), .samples = dst_framebuffer->Samples(),
.color_formats = dst_framebuffer->ColorAttachmentFormats(),
.depth_format = dst_framebuffer->DepthAttachmentFormat(),
}; };
const VkPipelineLayout layout = *one_texture_pipeline_layout; const VkPipelineLayout layout = *one_texture_pipeline_layout;
const VkSampler sampler = *nearest_sampler; const VkSampler sampler = *nearest_sampler;
const VkPipeline pipeline = FindOrEmplaceBlitColorMSAAPipeline(key); const VkPipeline pipeline = FindOrEmplaceBlitColorMSAAPipeline(key, dst_framebuffer);
const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D); const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D);
RecordShaderReadBarrier(scheduler, src_image_view); RecordShaderReadBarrier(scheduler, src_image_view);
@@ -703,7 +738,7 @@ void BlitImageHelper::ResolveDepthStencil(const Framebuffer* dst_framebuffer,
const bool resolve_stencil = const bool resolve_stencil =
dst_framebuffer->HasAspectStencilBit() && device.IsExtShaderStencilExportSupported(); dst_framebuffer->HasAspectStencilBit() && device.IsExtShaderStencilExportSupported();
const VkPipeline pipeline = const VkPipeline pipeline =
FindOrEmplaceResolveDepthStencilPipeline(dst_framebuffer->RenderPass(), resolve_stencil); FindOrEmplaceResolveDepthStencilPipeline(dst_framebuffer, resolve_stencil);
const VkPipelineLayout layout = const VkPipelineLayout layout =
resolve_stencil ? *two_textures_pipeline_layout : *one_texture_pipeline_layout; resolve_stencil ? *two_textures_pipeline_layout : *one_texture_pipeline_layout;
const VkSampler sampler = *nearest_sampler; const VkSampler sampler = *nearest_sampler;
@@ -747,10 +782,12 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer,
const BlitImagePipelineKey key{ const BlitImagePipelineKey key{
.renderpass = dst_framebuffer->RenderPass(), .renderpass = dst_framebuffer->RenderPass(),
.operation = operation, .operation = operation,
.color_formats = dst_framebuffer->ColorAttachmentFormats(),
.depth_format = dst_framebuffer->DepthAttachmentFormat(),
}; };
const VkPipelineLayout layout = *two_textures_pipeline_layout; const VkPipelineLayout layout = *two_textures_pipeline_layout;
const VkSampler sampler = *nearest_sampler; const VkSampler sampler = *nearest_sampler;
const VkPipeline pipeline = FindOrEmplaceDepthStencilPipeline(key); const VkPipeline pipeline = FindOrEmplaceDepthStencilPipeline(key, dst_framebuffer);
const VkImageView src_depth_view = src_image_view.DepthView(); const VkImageView src_depth_view = src_image_view.DepthView();
const VkImageView src_stencil_view = src_image_view.StencilView(); const VkImageView src_stencil_view = src_image_view.StencilView();
@@ -772,25 +809,25 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer,
void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer, void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer,
const ImageView& src_image_view) { const ImageView& src_image_view) {
ConvertDepthToColorPipeline(convert_d32_to_r32_pipeline, dst_framebuffer->RenderPass()); ConvertDepthToColorPipeline(convert_d32_to_r32_pipeline, dst_framebuffer);
Convert(*convert_d32_to_r32_pipeline, dst_framebuffer, src_image_view); Convert(*convert_d32_to_r32_pipeline, dst_framebuffer, src_image_view);
} }
void BlitImageHelper::ConvertR32ToD32(const Framebuffer* dst_framebuffer, void BlitImageHelper::ConvertR32ToD32(const Framebuffer* dst_framebuffer,
const ImageView& src_image_view) { const ImageView& src_image_view) {
ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer->RenderPass()); ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer);
Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view); Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view);
} }
void BlitImageHelper::ConvertD16ToR16(const Framebuffer* dst_framebuffer, void BlitImageHelper::ConvertD16ToR16(const Framebuffer* dst_framebuffer,
const ImageView& src_image_view) { const ImageView& src_image_view) {
ConvertDepthToColorPipeline(convert_d16_to_r16_pipeline, dst_framebuffer->RenderPass()); ConvertDepthToColorPipeline(convert_d16_to_r16_pipeline, dst_framebuffer);
Convert(*convert_d16_to_r16_pipeline, dst_framebuffer, src_image_view); Convert(*convert_d16_to_r16_pipeline, dst_framebuffer, src_image_view);
} }
void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer, void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer,
const ImageView& src_image_view) { const ImageView& src_image_view) {
ConvertColorToDepthPipeline(convert_r16_to_d16_pipeline, dst_framebuffer->RenderPass()); ConvertColorToDepthPipeline(convert_r16_to_d16_pipeline, dst_framebuffer);
Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view); Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view);
} }
@@ -801,35 +838,35 @@ void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer,
LOG_WARNING(Render_Vulkan, "ConvertABGR8ToD24S8 requires shader_stencil_export, skipping"); LOG_WARNING(Render_Vulkan, "ConvertABGR8ToD24S8 requires shader_stencil_export, skipping");
return; return;
} }
ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(), ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer,
convert_abgr8_to_d24s8_frag); convert_abgr8_to_d24s8_frag);
Convert(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view); Convert(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view);
} }
void BlitImageHelper::ConvertABGR8ToD32F(const Framebuffer* dst_framebuffer, void BlitImageHelper::ConvertABGR8ToD32F(const Framebuffer* dst_framebuffer,
const ImageView& src_image_view) { const ImageView& src_image_view) {
ConvertPipelineDepthTargetEx(convert_abgr8_to_d32f_pipeline, dst_framebuffer->RenderPass(), ConvertPipelineDepthTargetEx(convert_abgr8_to_d32f_pipeline, dst_framebuffer,
convert_abgr8_to_d32f_frag); convert_abgr8_to_d32f_frag);
Convert(*convert_abgr8_to_d32f_pipeline, dst_framebuffer, src_image_view); Convert(*convert_abgr8_to_d32f_pipeline, dst_framebuffer, src_image_view);
} }
void BlitImageHelper::ConvertD32FToABGR8(const Framebuffer* dst_framebuffer, void BlitImageHelper::ConvertD32FToABGR8(const Framebuffer* dst_framebuffer,
ImageView& src_image_view) { ImageView& src_image_view) {
ConvertPipelineColorTargetEx(convert_d32f_to_abgr8_pipeline, dst_framebuffer->RenderPass(), ConvertPipelineColorTargetEx(convert_d32f_to_abgr8_pipeline, dst_framebuffer,
convert_d32f_to_abgr8_frag); convert_d32f_to_abgr8_frag);
ConvertDepthStencil(*convert_d32f_to_abgr8_pipeline, dst_framebuffer, src_image_view); ConvertDepthStencil(*convert_d32f_to_abgr8_pipeline, dst_framebuffer, src_image_view);
} }
void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer,
ImageView& src_image_view) { ImageView& src_image_view) {
ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer->RenderPass(), ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer,
convert_d24s8_to_abgr8_frag); convert_d24s8_to_abgr8_frag);
ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view); ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view);
} }
void BlitImageHelper::ConvertS8D24ToABGR8(const Framebuffer* dst_framebuffer, void BlitImageHelper::ConvertS8D24ToABGR8(const Framebuffer* dst_framebuffer,
ImageView& src_image_view) { ImageView& src_image_view) {
ConvertPipelineColorTargetEx(convert_s8d24_to_abgr8_pipeline, dst_framebuffer->RenderPass(), ConvertPipelineColorTargetEx(convert_s8d24_to_abgr8_pipeline, dst_framebuffer,
convert_s8d24_to_abgr8_frag); convert_s8d24_to_abgr8_frag);
ConvertDepthStencil(*convert_s8d24_to_abgr8_pipeline, dst_framebuffer, src_image_view); ConvertDepthStencil(*convert_s8d24_to_abgr8_pipeline, dst_framebuffer, src_image_view);
} }
@@ -840,8 +877,10 @@ void BlitImageHelper::ClearColor(const Framebuffer* dst_framebuffer, u8 color_ma
const BlitImagePipelineKey key{ const BlitImagePipelineKey key{
.renderpass = dst_framebuffer->RenderPass(), .renderpass = dst_framebuffer->RenderPass(),
.operation = Tegra::Engines::Fermi2D::Operation::BlendPremult, .operation = Tegra::Engines::Fermi2D::Operation::BlendPremult,
.color_formats = dst_framebuffer->ColorAttachmentFormats(),
.depth_format = dst_framebuffer->DepthAttachmentFormat(),
}; };
const VkPipeline pipeline = FindOrEmplaceClearColorPipeline(key); const VkPipeline pipeline = FindOrEmplaceClearColorPipeline(key, dst_framebuffer);
const VkPipelineLayout layout = *clear_color_pipeline_layout; const VkPipelineLayout layout = *clear_color_pipeline_layout;
scheduler.RequestRenderpass(dst_framebuffer); scheduler.RequestRenderpass(dst_framebuffer);
scheduler.Record( scheduler.Record(
@@ -867,8 +906,10 @@ void BlitImageHelper::ClearDepthStencil(const Framebuffer* dst_framebuffer, bool
.stencil_mask = stencil_mask, .stencil_mask = stencil_mask,
.stencil_compare_mask = stencil_compare_mask, .stencil_compare_mask = stencil_compare_mask,
.stencil_ref = stencil_ref, .stencil_ref = stencil_ref,
.color_formats = dst_framebuffer->ColorAttachmentFormats(),
.depth_format = dst_framebuffer->DepthAttachmentFormat(),
}; };
const VkPipeline pipeline = FindOrEmplaceClearStencilPipeline(key); const VkPipeline pipeline = FindOrEmplaceClearStencilPipeline(key, dst_framebuffer);
const VkPipelineLayout layout = *clear_color_pipeline_layout; const VkPipelineLayout layout = *clear_color_pipeline_layout;
scheduler.RequestRenderpass(dst_framebuffer); scheduler.RequestRenderpass(dst_framebuffer);
scheduler.Record([pipeline, layout, clear_depth, dst_region](vk::CommandBuffer cmdbuf) { scheduler.Record([pipeline, layout, clear_depth, dst_region](vk::CommandBuffer cmdbuf) {
@@ -1140,12 +1181,14 @@ void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer
scheduler.InvalidateState(); scheduler.InvalidateState();
} }
VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key) { VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key,
const Framebuffer* framebuffer) {
const auto it = std::ranges::find(blit_color_keys, key); const auto it = std::ranges::find(blit_color_keys, key);
if (it != blit_color_keys.end()) { if (it != blit_color_keys.end()) {
return *blit_color_pipelines[std::distance(blit_color_keys.begin(), it)]; return *blit_color_pipelines[std::distance(blit_color_keys.begin(), it)];
} }
blit_color_keys.push_back(key); blit_color_keys.push_back(key);
const VkPipelineRenderingCreateInfo rendering_ci = MakePipelineRenderingCreateInfo(framebuffer);
const std::array stages = MakeStages(*full_screen_vert, *blit_color_to_color_frag); const std::array stages = MakeStages(*full_screen_vert, *blit_color_to_color_frag);
const VkPipelineColorBlendAttachmentState blend_attachment{ const VkPipelineColorBlendAttachmentState blend_attachment{
@@ -1173,7 +1216,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
blit_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ blit_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = key.renderpass ? nullptr : &rendering_ci,
.flags = 0, .flags = 0,
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
@@ -1195,17 +1238,19 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe
return *blit_color_pipelines.back(); return *blit_color_pipelines.back();
} }
VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key) { VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key,
const Framebuffer* framebuffer) {
const auto it = std::ranges::find(blit_depth_stencil_keys, key); const auto it = std::ranges::find(blit_depth_stencil_keys, key);
if (it != blit_depth_stencil_keys.end()) { if (it != blit_depth_stencil_keys.end()) {
return *blit_depth_stencil_pipelines[std::distance(blit_depth_stencil_keys.begin(), it)]; return *blit_depth_stencil_pipelines[std::distance(blit_depth_stencil_keys.begin(), it)];
} }
blit_depth_stencil_keys.push_back(key); blit_depth_stencil_keys.push_back(key);
const VkPipelineRenderingCreateInfo rendering_ci = MakePipelineRenderingCreateInfo(framebuffer);
const std::array stages = MakeStages(*full_screen_vert, *blit_depth_stencil_frag); const std::array stages = MakeStages(*full_screen_vert, *blit_depth_stencil_frag);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
blit_depth_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ blit_depth_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = key.renderpass ? nullptr : &rendering_ci,
.flags = 0, .flags = 0,
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
@@ -1227,38 +1272,46 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip
return *blit_depth_stencil_pipelines.back(); return *blit_depth_stencil_pipelines.back();
} }
VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipelineKey& key) { VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipelineKey& key,
const Framebuffer* framebuffer) {
const auto it = std::ranges::find(clear_color_keys, key); const auto it = std::ranges::find(clear_color_keys, key);
if (it != clear_color_keys.end()) { if (it != clear_color_keys.end()) {
return *clear_color_pipelines[std::distance(clear_color_keys.begin(), it)]; return *clear_color_pipelines[std::distance(clear_color_keys.begin(), it)];
} }
clear_color_keys.push_back(key); clear_color_keys.push_back(key);
const VkPipelineRenderingCreateInfo rendering_ci = MakePipelineRenderingCreateInfo(framebuffer);
const std::array stages = MakeStages(*clear_color_vert, *clear_color_frag); const std::array stages = MakeStages(*clear_color_vert, *clear_color_frag);
const VkPipelineColorBlendAttachmentState color_blend_attachment_state{ const u32 num_color = framebuffer->NumColorAttachments();
.blendEnable = VK_TRUE, constexpr VkColorComponentFlags full_write_mask =
.srcColorBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR, VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, VK_COLOR_COMPONENT_A_BIT;
.colorBlendOp = VK_BLEND_OP_ADD, std::array<VkPipelineColorBlendAttachmentState, VideoCommon::NUM_RT> blend_attachments{};
.srcAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_ALPHA, for (u32 index = 0; index < num_color; ++index) {
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA, blend_attachments[index] = VkPipelineColorBlendAttachmentState{
.alphaBlendOp = VK_BLEND_OP_ADD, .blendEnable = index == 0 ? VK_TRUE : VK_FALSE,
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | .srcColorBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR,
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
}; .colorBlendOp = VK_BLEND_OP_ADD,
.srcAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_ALPHA,
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA,
.alphaBlendOp = VK_BLEND_OP_ADD,
.colorWriteMask = index == 0 ? full_write_mask : VkColorComponentFlags{0},
};
}
const VkPipelineColorBlendStateCreateInfo color_blend_state_generic_create_info{ const VkPipelineColorBlendStateCreateInfo color_blend_state_generic_create_info{
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0, .flags = 0,
.logicOpEnable = VK_FALSE, .logicOpEnable = VK_FALSE,
.logicOp = VK_LOGIC_OP_CLEAR, .logicOp = VK_LOGIC_OP_CLEAR,
.attachmentCount = 1, .attachmentCount = num_color,
.pAttachments = &color_blend_attachment_state, .pAttachments = blend_attachments.data(),
.blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
}; };
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
clear_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ clear_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = key.renderpass ? nullptr : &rendering_ci,
.flags = 0, .flags = 0,
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
@@ -1281,13 +1334,26 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel
} }
VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline( VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline(
const BlitDepthStencilPipelineKey& key) { const BlitDepthStencilPipelineKey& key, const Framebuffer* framebuffer) {
const auto it = std::ranges::find(clear_stencil_keys, key); const auto it = std::ranges::find(clear_stencil_keys, key);
if (it != clear_stencil_keys.end()) { if (it != clear_stencil_keys.end()) {
return *clear_stencil_pipelines[std::distance(clear_stencil_keys.begin(), it)]; return *clear_stencil_pipelines[std::distance(clear_stencil_keys.begin(), it)];
} }
clear_stencil_keys.push_back(key); clear_stencil_keys.push_back(key);
const VkPipelineRenderingCreateInfo rendering_ci = MakePipelineRenderingCreateInfo(framebuffer);
const std::array stages = MakeStages(*clear_color_vert, *clear_stencil_frag); const std::array stages = MakeStages(*clear_color_vert, *clear_stencil_frag);
const u32 num_color = framebuffer->NumColorAttachments();
std::array<VkPipelineColorBlendAttachmentState, VideoCommon::NUM_RT> blend_attachments{};
const VkPipelineColorBlendStateCreateInfo color_blend_ci{
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.logicOpEnable = VK_FALSE,
.logicOp = VK_LOGIC_OP_CLEAR,
.attachmentCount = num_color,
.pAttachments = blend_attachments.data(),
.blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
};
const auto stencil = VkStencilOpState{ const auto stencil = VkStencilOpState{
.failOp = VK_STENCIL_OP_KEEP, .failOp = VK_STENCIL_OP_KEEP,
.passOp = VK_STENCIL_OP_REPLACE, .passOp = VK_STENCIL_OP_REPLACE,
@@ -1314,7 +1380,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline(
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
clear_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ clear_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = key.renderpass ? nullptr : &rendering_ci,
.flags = 0, .flags = 0,
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
@@ -1325,7 +1391,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline(
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.pDepthStencilState = &depth_stencil_ci, .pDepthStencilState = &depth_stencil_ci,
.pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, .pColorBlendState = &color_blend_ci,
.pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.layout = *clear_color_pipeline_layout, .layout = *clear_color_pipeline_layout,
.renderPass = key.renderpass, .renderPass = key.renderpass,
@@ -1336,12 +1402,14 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline(
return *clear_stencil_pipelines.back(); return *clear_stencil_pipelines.back();
} }
VkPipeline BlitImageHelper::FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPipelineKey& key) { VkPipeline BlitImageHelper::FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPipelineKey& key,
const Framebuffer* framebuffer) {
const auto it = std::ranges::find(blit_msaa_color_keys, key); const auto it = std::ranges::find(blit_msaa_color_keys, key);
if (it != blit_msaa_color_keys.end()) { if (it != blit_msaa_color_keys.end()) {
return *blit_msaa_color_pipelines[std::distance(blit_msaa_color_keys.begin(), it)]; return *blit_msaa_color_pipelines[std::distance(blit_msaa_color_keys.begin(), it)];
} }
blit_msaa_color_keys.push_back(key); blit_msaa_color_keys.push_back(key);
const VkPipelineRenderingCreateInfo rendering_ci = MakePipelineRenderingCreateInfo(framebuffer);
const std::array stages = MakeStages(*full_screen_vert, *blit_color_msaa_frag); const std::array stages = MakeStages(*full_screen_vert, *blit_color_msaa_frag);
const VkPipelineMultisampleStateCreateInfo multisample_ci{ const VkPipelineMultisampleStateCreateInfo multisample_ci{
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
@@ -1357,7 +1425,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPip
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
blit_msaa_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ blit_msaa_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = key.renderpass ? nullptr : &rendering_ci,
.flags = 0, .flags = 0,
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
@@ -1379,22 +1447,28 @@ VkPipeline BlitImageHelper::FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPip
return *blit_msaa_color_pipelines.back(); return *blit_msaa_color_pipelines.back();
} }
VkPipeline BlitImageHelper::FindOrEmplaceResolveDepthStencilPipeline(VkRenderPass renderpass, VkPipeline BlitImageHelper::FindOrEmplaceResolveDepthStencilPipeline(
bool resolve_stencil) { const Framebuffer* framebuffer, bool resolve_stencil) {
const VkRenderPass renderpass = framebuffer->RenderPass();
const ResolveDepthStencilPipelineKey key{
.renderpass = renderpass,
.depth_format = framebuffer->DepthAttachmentFormat(),
};
auto& keys = resolve_stencil ? resolve_depth_stencil_keys : resolve_depth_keys; auto& keys = resolve_stencil ? resolve_depth_stencil_keys : resolve_depth_keys;
auto& pipelines = resolve_stencil ? resolve_depth_stencil_pipelines : resolve_depth_pipelines; auto& pipelines = resolve_stencil ? resolve_depth_stencil_pipelines : resolve_depth_pipelines;
const auto it = std::ranges::find(keys, renderpass); const auto it = std::ranges::find(keys, key);
if (it != keys.end()) { if (it != keys.end()) {
return *pipelines[std::distance(keys.begin(), it)]; return *pipelines[std::distance(keys.begin(), it)];
} }
keys.push_back(renderpass); keys.push_back(key);
const VkPipelineRenderingCreateInfo rendering_ci = MakePipelineRenderingCreateInfo(framebuffer);
const std::array stages = const std::array stages =
MakeStages(*full_screen_vert, MakeStages(*full_screen_vert,
resolve_stencil ? *blit_depth_stencil_msaa_frag : *blit_depth_msaa_frag); resolve_stencil ? *blit_depth_stencil_msaa_frag : *blit_depth_msaa_frag);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = renderpass ? nullptr : &rendering_ci,
.flags = 0, .flags = 0,
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
@@ -1462,25 +1536,29 @@ VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyPipeline(const MSAACopyPipeline
return *msaa_copy_pipelines.back(); return *msaa_copy_pipelines.back();
} }
void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) { void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline,
ConvertPipeline(pipeline, renderpass, false); const Framebuffer* framebuffer) {
ConvertPipeline(pipeline, framebuffer, false);
} }
void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) { void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline,
ConvertPipeline(pipeline, renderpass, true); const Framebuffer* framebuffer) {
ConvertPipeline(pipeline, framebuffer, true);
} }
void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass, void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, const Framebuffer* framebuffer,
vk::ShaderModule& module, bool single_texture, vk::ShaderModule& module, bool single_texture,
bool is_target_depth) { bool is_target_depth) {
if (pipeline) { if (pipeline) {
return; return;
} }
const VkRenderPass renderpass = framebuffer->RenderPass();
const VkPipelineRenderingCreateInfo rendering_ci = MakePipelineRenderingCreateInfo(framebuffer);
const std::array stages = MakeStages(*full_screen_vert, *module); const std::array stages = MakeStages(*full_screen_vert, *module);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
pipeline = device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{ pipeline = device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = renderpass ? nullptr : &rendering_ci,
.flags = 0, .flags = 0,
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
@@ -1502,28 +1580,32 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass ren
}); });
} }
void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline,
const Framebuffer* framebuffer,
vk::ShaderModule& module) { vk::ShaderModule& module) {
ConvertPipelineEx(pipeline, renderpass, module, false, false); ConvertPipelineEx(pipeline, framebuffer, module, false, false);
} }
void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline,
const Framebuffer* framebuffer,
vk::ShaderModule& module) { vk::ShaderModule& module) {
ConvertPipelineEx(pipeline, renderpass, module, true, true); ConvertPipelineEx(pipeline, framebuffer, module, true, true);
} }
void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, const Framebuffer* framebuffer,
bool is_target_depth) { bool is_target_depth) {
if (pipeline) { if (pipeline) {
return; return;
} }
const VkRenderPass renderpass = framebuffer->RenderPass();
const VkPipelineRenderingCreateInfo rendering_ci = MakePipelineRenderingCreateInfo(framebuffer);
VkShaderModule frag_shader = VkShaderModule frag_shader =
is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag; is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag;
const std::array stages = MakeStages(*full_screen_vert, frag_shader); const std::array stages = MakeStages(*full_screen_vert, frag_shader);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
pipeline = device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{ pipeline = device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = renderpass ? nullptr : &rendering_ci,
.flags = 0, .flags = 0,
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
+32 -14
View File
@@ -33,6 +33,8 @@ struct BlitImagePipelineKey {
VkRenderPass renderpass; VkRenderPass renderpass;
Tegra::Engines::Fermi2D::Operation operation; Tegra::Engines::Fermi2D::Operation operation;
std::array<VkFormat, VideoCommon::NUM_RT> color_formats;
VkFormat depth_format;
}; };
struct BlitDepthStencilPipelineKey { struct BlitDepthStencilPipelineKey {
@@ -43,6 +45,8 @@ struct BlitDepthStencilPipelineKey {
u8 stencil_mask; u8 stencil_mask;
u32 stencil_compare_mask; u32 stencil_compare_mask;
u32 stencil_ref; u32 stencil_ref;
std::array<VkFormat, VideoCommon::NUM_RT> color_formats;
VkFormat depth_format;
}; };
struct MSAACopyPipelineKey { struct MSAACopyPipelineKey {
@@ -58,6 +62,15 @@ struct BlitMSAAPipelineKey {
VkRenderPass renderpass; VkRenderPass renderpass;
VkSampleCountFlagBits samples; VkSampleCountFlagBits samples;
std::array<VkFormat, VideoCommon::NUM_RT> color_formats;
VkFormat depth_format;
};
struct ResolveDepthStencilPipelineKey {
constexpr auto operator<=>(const ResolveDepthStencilPipelineKey&) const noexcept = default;
VkRenderPass renderpass;
VkFormat depth_format;
}; };
class BlitImageHelper { class BlitImageHelper {
@@ -123,31 +136,36 @@ private:
void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
ImageView& src_image_view); ImageView& src_image_view);
[[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key); [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key,
const Framebuffer* framebuffer);
[[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key,
const Framebuffer* framebuffer);
[[nodiscard]] VkPipeline FindOrEmplaceClearColorPipeline(const BlitImagePipelineKey& key); [[nodiscard]] VkPipeline FindOrEmplaceClearColorPipeline(const BlitImagePipelineKey& key,
const Framebuffer* framebuffer);
[[nodiscard]] VkPipeline FindOrEmplaceClearStencilPipeline( [[nodiscard]] VkPipeline FindOrEmplaceClearStencilPipeline(
const BlitDepthStencilPipelineKey& key); const BlitDepthStencilPipelineKey& key, const Framebuffer* framebuffer);
[[nodiscard]] VkPipeline FindOrEmplaceMSAACopyPipeline(const MSAACopyPipelineKey& key); [[nodiscard]] VkPipeline FindOrEmplaceMSAACopyPipeline(const MSAACopyPipelineKey& key);
[[nodiscard]] VkPipeline FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPipelineKey& key); [[nodiscard]] VkPipeline FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPipelineKey& key,
[[nodiscard]] VkPipeline FindOrEmplaceResolveDepthStencilPipeline(VkRenderPass renderpass, const Framebuffer* framebuffer);
[[nodiscard]] VkPipeline FindOrEmplaceResolveDepthStencilPipeline(const Framebuffer* framebuffer,
bool resolve_stencil); bool resolve_stencil);
void ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, bool is_target_depth); void ConvertPipeline(vk::Pipeline& pipeline, const Framebuffer* framebuffer,
bool is_target_depth);
void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, const Framebuffer* framebuffer);
void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, const Framebuffer* framebuffer);
void ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass, void ConvertPipelineEx(vk::Pipeline& pipeline, const Framebuffer* framebuffer,
vk::ShaderModule& module, bool single_texture, bool is_target_depth); vk::ShaderModule& module, bool single_texture, bool is_target_depth);
void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, const Framebuffer* framebuffer,
vk::ShaderModule& module); vk::ShaderModule& module);
void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, const Framebuffer* framebuffer,
vk::ShaderModule& module); vk::ShaderModule& module);
const Device& device; const Device& device;
@@ -195,9 +213,9 @@ private:
std::vector<vk::Pipeline> msaa_copy_pipelines; std::vector<vk::Pipeline> msaa_copy_pipelines;
std::vector<BlitMSAAPipelineKey> blit_msaa_color_keys; std::vector<BlitMSAAPipelineKey> blit_msaa_color_keys;
std::vector<vk::Pipeline> blit_msaa_color_pipelines; std::vector<vk::Pipeline> blit_msaa_color_pipelines;
std::vector<VkRenderPass> resolve_depth_keys; std::vector<ResolveDepthStencilPipelineKey> resolve_depth_keys;
std::vector<vk::Pipeline> resolve_depth_pipelines; std::vector<vk::Pipeline> resolve_depth_pipelines;
std::vector<VkRenderPass> resolve_depth_stencil_keys; std::vector<ResolveDepthStencilPipelineKey> resolve_depth_stencil_keys;
std::vector<vk::Pipeline> resolve_depth_stencil_pipelines; std::vector<vk::Pipeline> resolve_depth_stencil_pipelines;
struct MSAACopyResources { struct MSAACopyResources {
u64 tick; u64 tick;
@@ -4,7 +4,6 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <array> #include <array>
#include <memory> #include <memory>
#include <numeric> #include <numeric>
@@ -18,8 +17,6 @@
#include "common/div_ceil.h" #include "common/div_ceil.h"
#include "common/vector_math.h" #include "common/vector_math.h"
#include "video_core/host_shaders/astc_decoder_comp_spv.h" #include "video_core/host_shaders/astc_decoder_comp_spv.h"
#include "video_core/host_shaders/astc_decoder_frag_spv.h"
#include "video_core/host_shaders/astc_decoder_vert_spv.h"
#include "video_core/host_shaders/queries_prefix_scan_sum_comp_spv.h" #include "video_core/host_shaders/queries_prefix_scan_sum_comp_spv.h"
#include "video_core/host_shaders/queries_prefix_scan_sum_nosubgroups_comp_spv.h" #include "video_core/host_shaders/queries_prefix_scan_sum_nosubgroups_comp_spv.h"
#include "video_core/host_shaders/resolve_conditional_render_comp_spv.h" #include "video_core/host_shaders/resolve_conditional_render_comp_spv.h"
@@ -28,11 +25,8 @@
#include "video_core/host_shaders/block_linear_unswizzle_3d_bcn_comp_spv.h" #include "video_core/host_shaders/block_linear_unswizzle_3d_bcn_comp_spv.h"
#include "video_core/renderer_vulkan/vk_compute_pass.h" #include "video_core/renderer_vulkan/vk_compute_pass.h"
#include "video_core/surface.h" #include "video_core/surface.h"
#include "video_core/renderer_vulkan/maxwell_to_vk.h"
#include "video_core/renderer_vulkan/vk_descriptor_pool.h" #include "video_core/renderer_vulkan/vk_descriptor_pool.h"
#include "video_core/renderer_vulkan/vk_render_pass_cache.h"
#include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/renderer_vulkan/vk_shader_util.h"
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
#include "video_core/renderer_vulkan/vk_update_descriptor.h" #include "video_core/renderer_vulkan/vk_update_descriptor.h"
#include "video_core/texture_cache/accelerated_swizzle.h" #include "video_core/texture_cache/accelerated_swizzle.h"
@@ -619,394 +613,7 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, image_barrier); vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, image_barrier);
}); });
} scheduler.Finish();
namespace {
struct AstcFragPushConstants {
std::array<u32, 2> blocks_dims;
u32 layer_stride;
u32 block_size;
u32 x_shift;
u32 block_height;
u32 block_height_mask;
u32 dest_layer;
};
constexpr VkDescriptorSetLayoutBinding ASTC_FRAG_BINDING{
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.pImmutableSamplers = nullptr,
};
constexpr VkDescriptorUpdateTemplateEntry ASTC_FRAG_TEMPLATE{
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.offset = 0,
.stride = sizeof(DescriptorUpdateEntry),
};
constexpr DescriptorBankInfo ASTC_FRAG_BANK_INFO{
.uniform_buffers = 0,
.storage_buffers = 1,
.texture_buffers = 0,
.image_buffers = 0,
.textures = 0,
.images = 0,
.score = 1,
};
constexpr VkPushConstantRange ASTC_FRAG_PUSH_CONSTANT_RANGE{
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.offset = 0,
.size = static_cast<u32>(sizeof(AstcFragPushConstants)),
};
constexpr VkPipelineVertexInputStateCreateInfo ASTC_FRAG_VERTEX_INPUT{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.vertexBindingDescriptionCount = 0,
.pVertexBindingDescriptions = nullptr,
.vertexAttributeDescriptionCount = 0,
.pVertexAttributeDescriptions = nullptr,
};
constexpr VkPipelineInputAssemblyStateCreateInfo ASTC_FRAG_INPUT_ASSEMBLY{
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
.primitiveRestartEnable = VK_FALSE,
};
constexpr VkPipelineViewportStateCreateInfo ASTC_FRAG_VIEWPORT{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.viewportCount = 1,
.pViewports = nullptr,
.scissorCount = 1,
.pScissors = nullptr,
};
constexpr VkPipelineRasterizationStateCreateInfo ASTC_FRAG_RASTERIZATION{
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.depthClampEnable = VK_FALSE,
.rasterizerDiscardEnable = VK_FALSE,
.polygonMode = VK_POLYGON_MODE_FILL,
.cullMode = VK_CULL_MODE_NONE,
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
.depthBiasEnable = VK_FALSE,
.depthBiasConstantFactor = 0.0f,
.depthBiasClamp = 0.0f,
.depthBiasSlopeFactor = 0.0f,
.lineWidth = 1.0f,
};
constexpr VkPipelineMultisampleStateCreateInfo ASTC_FRAG_MULTISAMPLE{
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
.sampleShadingEnable = VK_FALSE,
.minSampleShading = 0.0f,
.pSampleMask = nullptr,
.alphaToCoverageEnable = VK_FALSE,
.alphaToOneEnable = VK_FALSE,
};
constexpr VkPipelineColorBlendAttachmentState ASTC_FRAG_BLEND_ATTACHMENT{
.blendEnable = VK_FALSE,
.srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO,
.colorBlendOp = VK_BLEND_OP_ADD,
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
.alphaBlendOp = VK_BLEND_OP_ADD,
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
};
constexpr std::array ASTC_FRAG_DYNAMIC_STATES{VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR};
} // Anonymous namespace
ASTCDecoderFragmentPass::ASTCDecoderFragmentPass(
const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue_,
RenderPassCache& render_pass_cache_)
: device{device_}, scheduler{scheduler_},
compute_pass_descriptor_queue{compute_pass_descriptor_queue_},
render_pass_cache{render_pass_cache_},
descriptor_set_layout{device.GetLogical().CreateDescriptorSetLayout({
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.bindingCount = 1,
.pBindings = &ASTC_FRAG_BINDING,
})},
descriptor_template{device.GetLogical().CreateDescriptorUpdateTemplate({
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.descriptorUpdateEntryCount = 1,
.pDescriptorUpdateEntries = &ASTC_FRAG_TEMPLATE,
.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
.descriptorSetLayout = *descriptor_set_layout,
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.pipelineLayout = VK_NULL_HANDLE,
.set = 0,
})},
pipeline_layout{device.GetLogical().CreatePipelineLayout({
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.setLayoutCount = 1,
.pSetLayouts = descriptor_set_layout.address(),
.pushConstantRangeCount = 1,
.pPushConstantRanges = &ASTC_FRAG_PUSH_CONSTANT_RANGE,
})},
descriptor_allocator{descriptor_pool_.Allocator(device_, scheduler_, *descriptor_set_layout,
ASTC_FRAG_BANK_INFO)},
vertex_shader{BuildShader(device, ASTC_DECODER_VERT_SPV)},
fragment_shader{BuildShader(device, ASTC_DECODER_FRAG_SPV)} {}
ASTCDecoderFragmentPass::~ASTCDecoderFragmentPass() = default;
VkPipeline ASTCDecoderFragmentPass::FindOrEmplacePipeline(VkRenderPass render_pass) {
const auto it = std::ranges::find(pipeline_keys, render_pass);
if (it != pipeline_keys.end()) {
return *pipelines[std::distance(pipeline_keys.begin(), it)];
}
pipeline_keys.push_back(render_pass);
const std::array stages{
VkPipelineShaderStageCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.stage = VK_SHADER_STAGE_VERTEX_BIT,
.module = *vertex_shader,
.pName = "main",
.pSpecializationInfo = nullptr,
},
VkPipelineShaderStageCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
.module = *fragment_shader,
.pName = "main",
.pSpecializationInfo = nullptr,
},
};
const VkPipelineColorBlendStateCreateInfo color_blend{
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.logicOpEnable = VK_FALSE,
.logicOp = VK_LOGIC_OP_CLEAR,
.attachmentCount = 1,
.pAttachments = &ASTC_FRAG_BLEND_ATTACHMENT,
.blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
};
const VkPipelineDynamicStateCreateInfo dynamic_state{
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.dynamicStateCount = static_cast<u32>(ASTC_FRAG_DYNAMIC_STATES.size()),
.pDynamicStates = ASTC_FRAG_DYNAMIC_STATES.data(),
};
pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(),
.pVertexInputState = &ASTC_FRAG_VERTEX_INPUT,
.pInputAssemblyState = &ASTC_FRAG_INPUT_ASSEMBLY,
.pTessellationState = nullptr,
.pViewportState = &ASTC_FRAG_VIEWPORT,
.pRasterizationState = &ASTC_FRAG_RASTERIZATION,
.pMultisampleState = &ASTC_FRAG_MULTISAMPLE,
.pDepthStencilState = nullptr,
.pColorBlendState = &color_blend,
.pDynamicState = &dynamic_state,
.layout = *pipeline_layout,
.renderPass = render_pass,
.subpass = 0,
.basePipelineHandle = VK_NULL_HANDLE,
.basePipelineIndex = 0,
}));
return *pipelines.back();
}
void ASTCDecoderFragmentPass::Assemble(Image& image, const StagingBufferRef& map,
std::span<const VideoCommon::SwizzleParameters> swizzles,
VideoCore::Surface::PixelFormat decoded_format) {
using namespace VideoCommon::Accelerated;
while (!frame_resources.empty() && scheduler.IsFree(frame_resources.front().tick)) {
frame_resources.pop_front();
}
const std::array<u32, 2> block_dims{
VideoCore::Surface::DefaultBlockWidth(image.info.format),
VideoCore::Surface::DefaultBlockHeight(image.info.format),
};
RenderPassKey key{};
key.color_formats.fill(VideoCore::Surface::PixelFormat::Invalid);
key.color_formats[0] = decoded_format;
key.depth_format = VideoCore::Surface::PixelFormat::Invalid;
key.samples = VK_SAMPLE_COUNT_1_BIT;
const VkRenderPass render_pass = render_pass_cache.Get(key);
const VkPipeline pipeline = FindOrEmplacePipeline(render_pass);
const VkFormat vk_format =
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, decoded_format).format;
const VkImage vk_image = image.Handle();
const VkImageAspectFlags aspect_mask = image.AspectMask();
scheduler.RequestOutsideRenderPassOperationContext();
const bool is_initialized = image.ExchangeInitialization();
scheduler.Record([vk_image, aspect_mask, is_initialized](vk::CommandBuffer cmdbuf) {
const VkImageMemoryBarrier barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = static_cast<VkAccessFlags>(
is_initialized ? VK_ACCESS_SHADER_READ_BIT : VK_ACCESS_NONE),
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = vk_image,
.subresourceRange{
.aspectMask = aspect_mask,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, barrier);
});
for (const VideoCommon::SwizzleParameters& swizzle : swizzles) {
const size_t input_offset = swizzle.buffer_offset + map.offset;
const auto params = MakeBlockLinearSwizzle2DParams(swizzle, image.info);
const u32 level = swizzle.level;
const u32 width = std::max(1u, image.info.size.width >> level);
const u32 height = std::max(1u, image.info.size.height >> level);
const u32 layers = image.info.resources.layers;
for (u32 layer = 0; layer < layers; ++layer) {
vk::ImageView view = device.GetLogical().CreateImageView(VkImageViewCreateInfo{
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.image = vk_image,
.viewType = VK_IMAGE_VIEW_TYPE_2D,
.format = vk_format,
.components{},
.subresourceRange{
.aspectMask = aspect_mask,
.baseMipLevel = level,
.levelCount = 1,
.baseArrayLayer = layer,
.layerCount = 1,
},
});
vk::Framebuffer framebuffer =
device.GetLogical().CreateFramebuffer(VkFramebufferCreateInfo{
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.renderPass = render_pass,
.attachmentCount = 1,
.pAttachments = view.address(),
.width = width,
.height = height,
.layers = 1,
});
const AstcFragPushConstants pc{
.blocks_dims = block_dims,
.layer_stride = params.layer_stride,
.block_size = params.block_size,
.x_shift = params.x_shift,
.block_height = params.block_height,
.block_height_mask = params.block_height_mask,
.dest_layer = layer,
};
compute_pass_descriptor_queue.Acquire(scheduler, 1);
compute_pass_descriptor_queue.AddBuffer(map.buffer, input_offset,
image.guest_size_bytes - swizzle.buffer_offset);
const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()};
scheduler.Record([this, pipeline, render_pass, descriptor_data, pc, width, height,
fb = *framebuffer](vk::CommandBuffer cmdbuf) {
const VkDescriptorSet set = descriptor_allocator.Commit();
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
const VkRenderPassBeginInfo begin{
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.pNext = nullptr,
.renderPass = render_pass,
.framebuffer = fb,
.renderArea{.offset = {0, 0}, .extent = {width, height}},
.clearValueCount = 0,
.pClearValues = nullptr,
};
const VkViewport viewport{
.x = 0.0f,
.y = 0.0f,
.width = static_cast<float>(width),
.height = static_cast<float>(height),
.minDepth = 0.0f,
.maxDepth = 1.0f,
};
const VkRect2D scissor{.offset = {0, 0}, .extent = {width, height}};
cmdbuf.BeginRenderPass(begin, VK_SUBPASS_CONTENTS_INLINE);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
cmdbuf.SetViewport(0, viewport);
cmdbuf.SetScissor(0, scissor);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline_layout, 0, set,
{});
cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, pc);
cmdbuf.Draw(3, 1, 0, 0);
cmdbuf.EndRenderPass();
});
frame_resources.push_back(FrameResources{
.tick = scheduler.CurrentTick(),
.view = std::move(view),
.framebuffer = std::move(framebuffer),
});
}
}
scheduler.Record([vk_image, aspect_mask](vk::CommandBuffer cmdbuf) {
const VkImageMemoryBarrier barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = vk_image,
.subresourceRange{
.aspectMask = aspect_mask,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, barrier);
});
scheduler.InvalidateState();
} }
constexpr u32 BL3D_BINDING_INPUT_BUFFER = 0; constexpr u32 BL3D_BINDING_INPUT_BUFFER = 0;
@@ -6,15 +6,12 @@
#pragma once #pragma once
#include <deque>
#include <optional> #include <optional>
#include <span> #include <span>
#include <utility> #include <utility>
#include <vector>
#include "common/common_types.h" #include "common/common_types.h"
#include "video_core/engines/maxwell_3d.h" #include "video_core/engines/maxwell_3d.h"
#include "video_core/surface.h"
#include "video_core/renderer_vulkan/vk_descriptor_pool.h" #include "video_core/renderer_vulkan/vk_descriptor_pool.h"
#include "video_core/renderer_vulkan/vk_update_descriptor.h" #include "video_core/renderer_vulkan/vk_update_descriptor.h"
#include "video_core/texture_cache/types.h" #include "video_core/texture_cache/types.h"
@@ -140,44 +137,6 @@ private:
MemoryAllocator& memory_allocator; MemoryAllocator& memory_allocator;
}; };
class RenderPassCache;
class ASTCDecoderFragmentPass final {
public:
explicit ASTCDecoderFragmentPass(const Device& device_, Scheduler& scheduler_,
DescriptorPool& descriptor_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue_,
RenderPassCache& render_pass_cache_);
~ASTCDecoderFragmentPass();
void Assemble(Image& image, const StagingBufferRef& map,
std::span<const VideoCommon::SwizzleParameters> swizzles,
VideoCore::Surface::PixelFormat decoded_format);
private:
VkPipeline FindOrEmplacePipeline(VkRenderPass render_pass);
const Device& device;
Scheduler& scheduler;
ComputePassDescriptorQueue& compute_pass_descriptor_queue;
RenderPassCache& render_pass_cache;
vk::DescriptorSetLayout descriptor_set_layout;
vk::DescriptorUpdateTemplate descriptor_template;
vk::PipelineLayout pipeline_layout;
DescriptorAllocator descriptor_allocator;
vk::ShaderModule vertex_shader;
vk::ShaderModule fragment_shader;
std::vector<VkRenderPass> pipeline_keys;
std::vector<vk::Pipeline> pipelines;
struct FrameResources {
u64 tick;
vk::ImageView view;
vk::Framebuffer framebuffer;
};
std::deque<FrameResources> frame_resources;
};
class BlockLinearUnswizzle3DPass final : public ComputePass { class BlockLinearUnswizzle3DPass final : public ComputePass {
public: public:
explicit BlockLinearUnswizzle3DPass(const Device& device_, Scheduler& scheduler_, explicit BlockLinearUnswizzle3DPass(const Device& device_, Scheduler& scheduler_,
@@ -290,7 +290,10 @@ GraphicsPipeline::GraphicsPipeline(
descriptor_update_template = descriptor_update_template =
builder.CreateTemplate(set_layout, *pipeline_layout, uses_push_descriptor); builder.CreateTemplate(set_layout, *pipeline_layout, uses_push_descriptor);
const VkRenderPass render_pass{render_pass_cache.Get(MakeRenderPassKey(key.state, device))}; VkRenderPass render_pass{};
if (!device.IsKhrDynamicRenderingSupported()) {
render_pass = render_pass_cache.Get(MakeRenderPassKey(key.state, device));
}
Validate(); Validate();
try { try {
MakePipeline(render_pass); MakePipeline(render_pass);
@@ -996,9 +999,47 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR;
} }
const RenderPassKey renderpass_key{MakeRenderPassKey(key.state, device)};
std::array<VkFormat, Maxwell::NumRenderTargets> color_attachment_formats{};
for (size_t index = 0; index < renderpass_key.color_formats.size(); ++index) {
const PixelFormat pixel_format{renderpass_key.color_formats[index]};
if (pixel_format == PixelFormat::Invalid) {
color_attachment_formats[index] = VK_FORMAT_UNDEFINED;
continue;
}
color_attachment_formats[index] =
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, pixel_format).format;
}
VkFormat depth_attachment_format{VK_FORMAT_UNDEFINED};
VkFormat stencil_attachment_format{VK_FORMAT_UNDEFINED};
if (renderpass_key.depth_format != PixelFormat::Invalid) {
const VkFormat format{
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true,
renderpass_key.depth_format)
.format};
const auto surface_type{VideoCore::Surface::GetFormatType(renderpass_key.depth_format)};
if (surface_type == VideoCore::Surface::SurfaceType::Depth ||
surface_type == VideoCore::Surface::SurfaceType::DepthStencil) {
depth_attachment_format = format;
}
if (surface_type == VideoCore::Surface::SurfaceType::Stencil ||
surface_type == VideoCore::Surface::SurfaceType::DepthStencil) {
stencil_attachment_format = format;
}
}
const VkPipelineRenderingCreateInfo rendering_ci{
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
.pNext = nullptr,
.viewMask = 0,
.colorAttachmentCount = static_cast<u32>(NumAttachments(key.state)),
.pColorAttachmentFormats = color_attachment_formats.data(),
.depthAttachmentFormat = depth_attachment_format,
.stencilAttachmentFormat = stencil_attachment_format,
};
pipeline = device.GetLogical().CreateGraphicsPipeline({ pipeline = device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = device.IsKhrDynamicRenderingSupported() ? &rendering_ci : nullptr,
.flags = flags, .flags = flags,
.stageCount = static_cast<u32>(shader_stages.size()), .stageCount = static_cast<u32>(shader_stages.size()),
.pStages = shader_stages.data(), .pStages = shader_stages.data(),
@@ -167,7 +167,6 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
} }
const Shader::Stage stage{program.stage}; const Shader::Stage stage{program.stage};
const bool has_geometry{key.unique_hashes[4] != 0 && !programs[4].is_geometry_passthrough}; const bool has_geometry{key.unique_hashes[4] != 0 && !programs[4].is_geometry_passthrough};
const bool has_tessellation{key.unique_hashes[3] != 0};
const bool gl_ndc{key.state.ndc_minus_one_to_one != 0}; const bool gl_ndc{key.state.ndc_minus_one_to_one != 0};
const float point_size{std::bit_cast<float>(key.state.point_size)}; const float point_size{std::bit_cast<float>(key.state.point_size)};
switch (stage) { switch (stage) {
@@ -186,9 +185,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
LOG_WARNING(Render_Vulkan, "XFB requested in pipeline key but device lacks VK_EXT_transform_feedback; ignoring XFB decorations"); LOG_WARNING(Render_Vulkan, "XFB requested in pipeline key but device lacks VK_EXT_transform_feedback; ignoring XFB decorations");
} }
} }
if (!has_tessellation) { info.convert_depth_mode = gl_ndc;
info.convert_depth_mode = gl_ndc;
}
} }
if (key.state.dynamic_vertex_input) { if (key.state.dynamic_vertex_input) {
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) { for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
@@ -227,9 +224,6 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
ASSERT(false); ASSERT(false);
return Shader::TessSpacing::Equal; return Shader::TessSpacing::Equal;
}(); }();
if (!has_geometry) {
info.convert_depth_mode = gl_ndc;
}
break; break;
case Shader::Stage::Geometry: case Shader::Stage::Geometry:
if (program.output_topology == Shader::OutputTopology::PointList) { if (program.output_topology == Shader::OutputTopology::PointList) {
@@ -773,7 +773,6 @@ bool RasterizerVulkan::OnCPUWrite(DAddr addr, u64 size) {
} }
static constexpr bool ENABLE_TEXTURE_CACHE_INVALIDATION_SKIP = true; static constexpr bool ENABLE_TEXTURE_CACHE_INVALIDATION_SKIP = true;
static constexpr bool ENABLE_FINE_GRAINED_TRACKER_LOCK = true;
void RasterizerVulkan::OnCacheInvalidation(DAddr addr, u64 size) { void RasterizerVulkan::OnCacheInvalidation(DAddr addr, u64 size) {
if (addr == 0 || size == 0) { if (addr == 0 || size == 0) {
@@ -785,9 +784,7 @@ void RasterizerVulkan::OnCacheInvalidation(DAddr addr, u64 size) {
std::scoped_lock lock{texture_cache.mutex}; std::scoped_lock lock{texture_cache.mutex};
texture_cache.WriteMemory(addr, size); texture_cache.WriteMemory(addr, size);
} }
if (ENABLE_FINE_GRAINED_TRACKER_LOCK) { {
buffer_cache.CpuWriteInvalidate(addr, size);
} else {
std::scoped_lock lock{buffer_cache.mutex}; std::scoped_lock lock{buffer_cache.mutex};
buffer_cache.WriteMemory(addr, size); buffer_cache.WriteMemory(addr, size);
} }
+149 -5
View File
@@ -93,13 +93,53 @@ void Scheduler::DispatchWork() {
} }
} }
void Scheduler::BeginDynamicRendering(const Framebuffer* framebuffer, const DeferredClear* clear) {
const VkExtent2D render_area = framebuffer->RenderArea();
std::array<VkImageView, 9> attachment_views{};
const auto& color_views = framebuffer->ColorAttachments();
for (size_t index = 0; index < color_views.size(); ++index) {
attachment_views[index] = color_views[index];
}
attachment_views[8] = framebuffer->DepthAttachment();
state.renderpass = VkRenderPass{};
state.framebuffer = VkFramebuffer{};
state.attachment_views = attachment_views;
state.color_resolve_views = framebuffer->ColorResolveAttachments();
state.color_resolve_modes = framebuffer->ColorResolveModes();
state.discards_msaa_color = framebuffer->DiscardsMsaaColor();
state.discards_msaa_depth = framebuffer->DiscardsMsaaDepth();
state.render_area = render_area;
state.num_color = framebuffer->NumColorAttachments();
state.has_depth = framebuffer->HasAspectDepthBit();
state.has_stencil = framebuffer->HasAspectStencilBit();
state.layer_count = framebuffer->NumLayers();
state.rendering = true;
if (GPU::Logging::IsActive() && Settings::values.gpu_log_vulkan_calls.GetValue()) {
const std::string render_pass_info =
fmt::format("renderArea={}x{}, numImages={}", render_area.width, render_area.height,
framebuffer->NumImages());
GPU::Logging::GPULogger::GetInstance().LogRenderPassBegin(render_pass_info);
}
RecordDynamicBegin(clear);
num_renderpass_images = framebuffer->NumImages();
renderpass_images = framebuffer->Images();
renderpass_image_ranges = framebuffer->ImageRanges();
}
void Scheduler::BeginRenderPassImpl(const Framebuffer* framebuffer, VkRenderPass renderpass, void Scheduler::BeginRenderPassImpl(const Framebuffer* framebuffer, VkRenderPass renderpass,
const VkClearValue* clear_values, u32 clear_value_count) { const VkClearValue* clear_values, u32 clear_value_count) {
const VkFramebuffer framebuffer_handle = framebuffer->Handle(); if (device.IsKhrDynamicRenderingSupported()) {
BeginDynamicRendering(framebuffer, nullptr);
return;
}
const VkExtent2D render_area = framebuffer->RenderArea(); const VkExtent2D render_area = framebuffer->RenderArea();
const VkFramebuffer framebuffer_handle = framebuffer->Handle();
state.renderpass = renderpass; state.renderpass = renderpass;
state.framebuffer = framebuffer_handle; state.framebuffer = framebuffer_handle;
state.render_area = render_area; state.render_area = render_area;
state.rendering = true;
if (GPU::Logging::IsActive() && Settings::values.gpu_log_vulkan_calls.GetValue()) { if (GPU::Logging::IsActive() && Settings::values.gpu_log_vulkan_calls.GetValue()) {
const std::string render_pass_info = const std::string render_pass_info =
@@ -141,6 +181,12 @@ void Scheduler::RealizeDeferredClear() {
const DeferredClear dc = deferred_clear; const DeferredClear dc = deferred_clear;
deferred_clear = {}; deferred_clear = {};
if (device.IsKhrDynamicRenderingSupported()) {
EndRenderPass();
BeginDynamicRendering(dc.framebuffer, &dc);
return;
}
std::array<VkClearValue, 9> clear_values{}; std::array<VkClearValue, 9> clear_values{};
u32 count = 0; u32 count = 0;
const RenderPassKey& base = dc.framebuffer->RenderPassKeyBase(); const RenderPassKey& base = dc.framebuffer->RenderPassKeyBase();
@@ -195,9 +241,25 @@ void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
RealizeDeferredClear(); RealizeDeferredClear();
return; return;
} }
const VkExtent2D render_area = framebuffer->RenderArea();
if (device.IsKhrDynamicRenderingSupported()) {
std::array<VkImageView, 9> attachment_views{};
const auto& color_views = framebuffer->ColorAttachments();
for (size_t index = 0; index < color_views.size(); ++index) {
attachment_views[index] = color_views[index];
}
attachment_views[8] = framebuffer->DepthAttachment();
if (state.rendering && attachment_views == state.attachment_views &&
render_area.width == state.render_area.width &&
render_area.height == state.render_area.height) {
return;
}
EndRenderPass();
BeginDynamicRendering(framebuffer, nullptr);
return;
}
const VkRenderPass renderpass = framebuffer->RenderPass(); const VkRenderPass renderpass = framebuffer->RenderPass();
const VkFramebuffer framebuffer_handle = framebuffer->Handle(); const VkFramebuffer framebuffer_handle = framebuffer->Handle();
const VkExtent2D render_area = framebuffer->RenderArea();
if (renderpass == state.renderpass && framebuffer_handle == state.framebuffer && if (renderpass == state.renderpass && framebuffer_handle == state.framebuffer &&
render_area.width == state.render_area.width && render_area.width == state.render_area.width &&
render_area.height == state.render_area.height) { render_area.height == state.render_area.height) {
@@ -372,6 +434,80 @@ void Scheduler::InvalidateState() {
state_tracker.InvalidateCommandBufferState(); state_tracker.InvalidateCommandBufferState();
} }
void Scheduler::RecordDynamicBegin(const DeferredClear* clear) {
const std::array<VkImageView, 9> views = state.attachment_views;
const std::array<VkImageView, 8> resolve_views = state.color_resolve_views;
const std::array<VkResolveModeFlagBits, 8> resolve_modes = state.color_resolve_modes;
const u32 num_color = state.num_color;
const bool has_depth = state.has_depth;
const bool has_stencil = state.has_stencil;
const u32 layers = state.layer_count;
const VkExtent2D render_area = state.render_area;
const u32 color_clear_mask = clear ? clear->color_clear_mask : 0u;
const u32 color_discard_mask =
clear != nullptr && state.discards_msaa_color ? clear->color_clear_mask : 0u;
const std::array<VkClearValue, 8> color_clear_values =
clear ? clear->color_values : std::array<VkClearValue, 8>{};
const bool ds_clear = clear != nullptr && clear->depth_stencil;
const VkClearValue ds_clear_value = clear ? clear->depth_stencil_value : VkClearValue{};
const bool ds_discard = state.discards_msaa_depth;
Record([views, resolve_views, resolve_modes, num_color, has_depth, has_stencil, layers,
render_area, color_clear_mask, color_discard_mask, color_clear_values, ds_clear,
ds_clear_value, ds_discard](vk::CommandBuffer cmdbuf) {
std::array<VkRenderingAttachmentInfo, VideoCommon::NUM_RT> color_infos{};
for (u32 index = 0; index < num_color; ++index) {
const bool clear_slot = ((color_clear_mask >> index) & 1u) != 0;
const VkImageView resolve_view = resolve_views[index];
const bool has_resolve = resolve_view != VK_NULL_HANDLE;
const bool discard_slot = has_resolve && ((color_discard_mask >> index) & 1u) != 0;
color_infos[index] = VkRenderingAttachmentInfo{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.pNext = nullptr,
.imageView = views[index],
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
.resolveMode = has_resolve ? resolve_modes[index] : VK_RESOLVE_MODE_NONE,
.resolveImageView = resolve_view,
.resolveImageLayout =
has_resolve ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED,
.loadOp = clear_slot ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = discard_slot ? VK_ATTACHMENT_STORE_OP_DONT_CARE
: VK_ATTACHMENT_STORE_OP_STORE,
.clearValue = clear_slot ? color_clear_values[index] : VkClearValue{},
};
}
const VkRenderingAttachmentInfo depth_info{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.pNext = nullptr,
.imageView = views[8],
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
.resolveMode = VK_RESOLVE_MODE_NONE,
.resolveImageView = VK_NULL_HANDLE,
.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.loadOp = ds_clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = ds_discard ? VK_ATTACHMENT_STORE_OP_DONT_CARE
: VK_ATTACHMENT_STORE_OP_STORE,
.clearValue = ds_clear ? ds_clear_value : VkClearValue{},
};
const VkRenderingInfo rendering_info{
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
.pNext = nullptr,
.flags = 0,
.renderArea =
{
.offset = {.x = 0, .y = 0},
.extent = render_area,
},
.layerCount = layers,
.viewMask = 0,
.colorAttachmentCount = num_color,
.pColorAttachments = color_infos.data(),
.pDepthAttachment = has_depth ? &depth_info : nullptr,
.pStencilAttachment = has_stencil ? &depth_info : nullptr,
};
cmdbuf.BeginRendering(rendering_info);
});
}
void Scheduler::EndPendingOperations() { void Scheduler::EndPendingOperations() {
query_cache->CounterReset(VideoCommon::QueryType::ZPassPixelCount64); query_cache->CounterReset(VideoCommon::QueryType::ZPassPixelCount64);
EndRenderPass(); EndRenderPass();
@@ -380,7 +516,7 @@ void Scheduler::EndPendingOperations() {
void Scheduler::EndRenderPass() void Scheduler::EndRenderPass()
{ {
RealizeDeferredClear(); RealizeDeferredClear();
if (!state.renderpass) { if (!state.rendering) {
return; return;
} }
@@ -398,7 +534,8 @@ void Scheduler::EndRenderPass()
Record([num_images = num_renderpass_images, Record([num_images = num_renderpass_images,
images = renderpass_images, images = renderpass_images,
ranges = renderpass_image_ranges, ranges = renderpass_image_ranges,
has_transform_feedback = device.IsExtTransformFeedbackSupported()]( has_transform_feedback = device.IsExtTransformFeedbackSupported(),
dynamic_rendering = device.IsKhrDynamicRenderingSupported()](
vk::CommandBuffer cmdbuf) { vk::CommandBuffer cmdbuf) {
std::array<VkImageMemoryBarrier, 9> barriers; std::array<VkImageMemoryBarrier, 9> barriers;
for (size_t i = 0; i < num_images; ++i) { for (size_t i = 0; i < num_images; ++i) {
@@ -435,7 +572,11 @@ void Scheduler::EndRenderPass()
.subresourceRange = range, .subresourceRange = range,
}; };
} }
cmdbuf.EndRenderPass(); if (dynamic_rendering) {
cmdbuf.EndRendering();
} else {
cmdbuf.EndRenderPass();
}
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
0, nullptr, nullptr, vk::Span(barriers.data(), num_images)); 0, nullptr, nullptr, vk::Span(barriers.data(), num_images));
@@ -453,6 +594,9 @@ void Scheduler::EndRenderPass()
}); });
state.renderpass = VkRenderPass{}; state.renderpass = VkRenderPass{};
state.framebuffer = VkFramebuffer{};
state.attachment_views = {};
state.rendering = false;
num_renderpass_images = 0; num_renderpass_images = 0;
} }
+16 -1
View File
@@ -71,7 +71,7 @@ public:
/// Returns true when a render pass is currently active in the scheduler state. /// Returns true when a render pass is currently active in the scheduler state.
bool IsRenderPassActive() const { bool IsRenderPassActive() const {
return state.renderpass != VK_NULL_HANDLE; return state.rendering;
} }
/// Update the pipeline to the current execution context. /// Update the pipeline to the current execution context.
@@ -250,8 +250,18 @@ private:
struct State { struct State {
VkRenderPass renderpass{}; VkRenderPass renderpass{};
VkFramebuffer framebuffer{}; VkFramebuffer framebuffer{};
std::array<VkImageView, 9> attachment_views{};
std::array<VkImageView, 8> color_resolve_views{};
std::array<VkResolveModeFlagBits, 8> color_resolve_modes{};
VkExtent2D render_area = {0, 0}; VkExtent2D render_area = {0, 0};
GraphicsPipeline* graphics_pipeline = nullptr; GraphicsPipeline* graphics_pipeline = nullptr;
bool rendering = false;
bool discards_msaa_color = false;
bool discards_msaa_depth = false;
u32 num_color = 0;
bool has_depth = false;
bool has_stencil = false;
u32 layer_count = 1;
bool is_rescaling = false; bool is_rescaling = false;
bool rescaling_defined = false; bool rescaling_defined = false;
bool needs_state_enable_refresh = false; bool needs_state_enable_refresh = false;
@@ -269,6 +279,9 @@ private:
void BeginRenderPassImpl(const Framebuffer* framebuffer, VkRenderPass renderpass, void BeginRenderPassImpl(const Framebuffer* framebuffer, VkRenderPass renderpass,
const VkClearValue* clear_values, u32 clear_value_count); const VkClearValue* clear_values, u32 clear_value_count);
/// Begins a dynamic rendering pass, optionally realizing a deferred clear via load ops.
void BeginDynamicRendering(const Framebuffer* framebuffer, const DeferredClear* clear);
/// If a deferred clear is pending. /// If a deferred clear is pending.
void RealizeDeferredClear(); void RealizeDeferredClear();
@@ -282,6 +295,8 @@ private:
void EndPendingOperations(); void EndPendingOperations();
void RecordDynamicBegin(const DeferredClear* clear);
void EndRenderPass(); void EndRenderPass();
void AcquireNewChunk(); void AcquireNewChunk();
@@ -54,6 +54,7 @@ using VideoCore::Surface::SurfaceType;
namespace { namespace {
constexpr bool ENABLE_MSAA_RESOLVE_CONSUME = true; constexpr bool ENABLE_MSAA_RESOLVE_CONSUME = true;
constexpr bool ENABLE_MSAA_COLOR_DISCARD = true; constexpr bool ENABLE_MSAA_COLOR_DISCARD = true;
constexpr bool ENABLE_MSAA_DEPTH_DISCARD = true;
constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
if (color == std::array<float, 4>{0, 0, 0, 0}) { if (color == std::array<float, 4>{0, 0, 0, 0}) {
@@ -129,9 +130,6 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
if (info.storage) { if (info.storage) {
usage |= VK_IMAGE_USAGE_STORAGE_BIT; usage |= VK_IMAGE_USAGE_STORAGE_BIT;
} }
if (IsPixelFormatASTC(format)) {
usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
return usage; return usage;
} }
@@ -914,10 +912,6 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched
if (Settings::values.accelerate_astc.GetValue() == Settings::AstcDecodeMode::Gpu) { if (Settings::values.accelerate_astc.GetValue() == Settings::AstcDecodeMode::Gpu) {
astc_decoder_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, astc_decoder_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool,
compute_pass_descriptor_queue, memory_allocator); compute_pass_descriptor_queue, memory_allocator);
if (device.IsTiler()) {
astc_decoder_fragment_pass.emplace(device, scheduler, descriptor_pool,
compute_pass_descriptor_queue, render_pass_cache);
}
} }
if (!device.IsKhrImageFormatListSupported()) { if (!device.IsKhrImageFormatListSupported()) {
return; return;
@@ -1048,6 +1042,32 @@ VkImageView TextureCacheRuntime::GetOrCreateResolveShadow(VkImage msaa_image, Vk
shadow.extent = extent; shadow.extent = extent;
shadow.layers = layers; shadow.layers = layers;
shadow.up_to_date = true; shadow.up_to_date = true;
if (device.IsKhrDynamicRenderingSupported()) {
scheduler.RecordWithUploadBuffer(
[image = *shadow.image, layers](vk::CommandBuffer, vk::CommandBuffer upload_cmdbuf) {
const VkImageMemoryBarrier barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = 0,
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image,
.subresourceRange{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = layers,
},
};
upload_cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0,
barrier);
});
}
return *shadow.view; return *shadow.view;
} }
@@ -1360,7 +1380,7 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
} }
void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view) { void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view) {
if (!dst->RenderPass()) { if (!dst->RenderPass() && !device.IsKhrDynamicRenderingSupported()) {
return; return;
} }
@@ -2690,7 +2710,7 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM
.height = key.size.height, .height = key.size.height,
}} { }} {
CreateFramebuffer(runtime, color_buffers, depth_buffer, key.is_rescaled); CreateFramebuffer(runtime, color_buffers, depth_buffer, key.is_rescaled);
if (runtime.device.HasDebuggingToolAttached()) { if (runtime.device.HasDebuggingToolAttached() && framebuffer) {
framebuffer.SetObjectNameEXT(VideoCommon::Name(key).c_str()); framebuffer.SetObjectNameEXT(VideoCommon::Name(key).c_str());
} }
} }
@@ -2733,6 +2753,12 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
image_ranges[num_images] = MakeSubresourceRange(color_buffer); image_ranges[num_images] = MakeSubresourceRange(color_buffer);
rt_map[index] = num_images; rt_map[index] = num_images;
samples = color_buffer->Samples(); samples = color_buffer->Samples();
color_attachments[index] = color_buffer->RenderTarget();
color_attachment_formats[index] =
MaxwellToVK::SurfaceFormat(runtime.device, FormatType::Optimal, true,
color_buffer->format)
.format;
num_color_attachments = static_cast<u32>(index + 1);
++num_images; ++num_images;
} }
const size_t num_colors = attachments.size(); const size_t num_colors = attachments.size();
@@ -2748,6 +2774,11 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
const VkImageSubresourceRange subresource_range = MakeSubresourceRange(depth_buffer); const VkImageSubresourceRange subresource_range = MakeSubresourceRange(depth_buffer);
image_ranges[num_images] = subresource_range; image_ranges[num_images] = subresource_range;
samples = depth_buffer->Samples(); samples = depth_buffer->Samples();
depth_attachment = depth_buffer->RenderTarget();
depth_attachment_format =
MaxwellToVK::SurfaceFormat(runtime.device, FormatType::Optimal, true,
depth_buffer->format)
.format;
++num_images; ++num_images;
has_depth = (subresource_range.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; has_depth = (subresource_range.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
has_stencil = (subresource_range.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; has_stencil = (subresource_range.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
@@ -2761,8 +2792,9 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
discard_msaa_color = discard_msaa_color =
ENABLE_MSAA_RESOLVE_CONSUME && ENABLE_MSAA_COLOR_DISCARD && do_resolve_color; ENABLE_MSAA_RESOLVE_CONSUME && ENABLE_MSAA_COLOR_DISCARD && do_resolve_color;
discard_msaa_depth = ENABLE_MSAA_RESOLVE_CONSUME && ENABLE_MSAA_DEPTH_DISCARD &&
samples != VK_SAMPLE_COUNT_1_BIT && has_depth && runtime.device.IsTiler();
renderpass = runtime.render_pass_cache.Get(renderpass_key);
render_pass_key = renderpass_key; render_pass_key = renderpass_key;
render_pass_cache = &runtime.render_pass_cache; render_pass_cache = &runtime.render_pass_cache;
render_area.width = (std::min)(render_area.width, width); render_area.width = (std::min)(render_area.width, width);
@@ -2777,10 +2809,15 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
} }
const VkFormat vk_format = const VkFormat vk_format =
MaxwellToVK::SurfaceFormat(runtime.device, FormatType::Optimal, true, format).format; MaxwellToVK::SurfaceFormat(runtime.device, FormatType::Optimal, true, format).format;
color_resolve_modes[index] = VideoCore::Surface::IsPixelFormatInteger(format)
? VK_RESOLVE_MODE_SAMPLE_ZERO_BIT
: VK_RESOLVE_MODE_AVERAGE_BIT;
if (ENABLE_MSAA_RESOLVE_CONSUME) { if (ENABLE_MSAA_RESOLVE_CONSUME) {
const VkImage msaa_image = images[rt_map[index]]; const VkImage msaa_image = images[rt_map[index]];
attachments.push_back(runtime.GetOrCreateResolveShadow(msaa_image, vk_format, const VkImageView shadow_view = runtime.GetOrCreateResolveShadow(
render_area, layers)); msaa_image, vk_format, render_area, layers);
color_resolve_attachments[index] = shadow_view;
attachments.push_back(shadow_view);
continue; continue;
} }
VkImageCreateInfo resolve_ci{ VkImageCreateInfo resolve_ci{
@@ -2819,6 +2856,33 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
.layerCount = layers, .layerCount = layers,
}, },
}); });
if (runtime.device.IsKhrDynamicRenderingSupported()) {
runtime.scheduler.RecordWithUploadBuffer(
[image = *resolve_image, layers](vk::CommandBuffer, vk::CommandBuffer upload_cmdbuf) {
const VkImageMemoryBarrier barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = 0,
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image,
.subresourceRange{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = layers,
},
};
upload_cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
0, barrier);
});
}
color_resolve_attachments[index] = *resolve_view;
attachments.push_back(*resolve_view); attachments.push_back(*resolve_view);
resolve_images.push_back(std::move(resolve_image)); resolve_images.push_back(std::move(resolve_image));
resolve_image_views.push_back(std::move(resolve_view)); resolve_image_views.push_back(std::move(resolve_view));
@@ -2826,6 +2890,11 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
} }
num_color_buffers = static_cast<u32>(num_colors); num_color_buffers = static_cast<u32>(num_colors);
layer_count = static_cast<u32>((std::max)(num_layers, 1));
if (runtime.device.IsKhrDynamicRenderingSupported()) {
return;
}
renderpass = runtime.render_pass_cache.Get(renderpass_key);
framebuffer = runtime.device.GetLogical().CreateFramebuffer({ framebuffer = runtime.device.GetLogical().CreateFramebuffer({
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@@ -2835,7 +2904,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
.pAttachments = attachments.data(), .pAttachments = attachments.data(),
.width = render_area.width, .width = render_area.width,
.height = render_area.height, .height = render_area.height,
.layers = static_cast<u32>((std::max)(num_layers, 1)), .layers = layer_count,
}); });
} }
@@ -2851,19 +2920,59 @@ VkRenderPass Framebuffer::RenderPassVariant(u32 color_clear_mask, bool depth_ste
return render_pass_cache->Get(key); return render_pass_cache->Get(key);
} }
void Framebuffer::BeginRendering(vk::CommandBuffer cmdbuf) const {
std::array<VkRenderingAttachmentInfo, NUM_RT> color_attachment_infos{};
for (size_t index = 0; index < num_color_attachments; ++index) {
color_attachment_infos[index] = VkRenderingAttachmentInfo{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.pNext = nullptr,
.imageView = color_attachments[index],
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
.resolveMode = VK_RESOLVE_MODE_NONE,
.resolveImageView = VK_NULL_HANDLE,
.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.clearValue = {},
};
}
const VkRenderingAttachmentInfo depth_attachment_info{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.pNext = nullptr,
.imageView = depth_attachment,
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
.resolveMode = VK_RESOLVE_MODE_NONE,
.resolveImageView = VK_NULL_HANDLE,
.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.clearValue = {},
};
const VkRenderingInfo rendering_info{
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
.pNext = nullptr,
.flags = 0,
.renderArea =
{
.offset = {.x = 0, .y = 0},
.extent = render_area,
},
.layerCount = layer_count,
.viewMask = 0,
.colorAttachmentCount = num_color_attachments,
.pColorAttachments = color_attachment_infos.data(),
.pDepthAttachment = has_depth ? &depth_attachment_info : nullptr,
.pStencilAttachment = has_stencil ? &depth_attachment_info : nullptr,
};
cmdbuf.BeginRendering(rendering_info);
}
void TextureCacheRuntime::AccelerateImageUpload( void TextureCacheRuntime::AccelerateImageUpload(
Image& image, const StagingBufferRef& map, Image& image, const StagingBufferRef& map,
std::span<const VideoCommon::SwizzleParameters> swizzles, std::span<const VideoCommon::SwizzleParameters> swizzles,
u32 z_start, u32 z_count) { u32 z_start, u32 z_count) {
if (IsPixelFormatASTC(image.info.format)) { if (IsPixelFormatASTC(image.info.format)) {
if (astc_decoder_fragment_pass) {
const VideoCore::Surface::PixelFormat decoded_format =
WillUseWidenedAstcFormat(device, image.info)
? VideoCore::Surface::PixelFormat::R32G32B32A32_FLOAT
: VideoCore::Surface::PixelFormat::A8B8G8R8_UNORM;
return astc_decoder_fragment_pass->Assemble(image, map, swizzles, decoded_format);
}
return astc_decoder_pass->Assemble(image, map, swizzles); return astc_decoder_pass->Assemble(image, map, swizzles);
} }
@@ -93,7 +93,7 @@ public:
void AccelerateImageUpload(Image&, const StagingBufferRef&, void AccelerateImageUpload(Image&, const StagingBufferRef&,
std::span<const VideoCommon::SwizzleParameters>, std::span<const VideoCommon::SwizzleParameters>,
u32 z_start = 0, u32 z_count = 0); u32 z_start, u32 z_count);
void InsertUploadMemoryBarrier() {} void InsertUploadMemoryBarrier() {}
@@ -147,7 +147,6 @@ public:
BlitImageHelper& blit_image_helper; BlitImageHelper& blit_image_helper;
RenderPassCache& render_pass_cache; RenderPassCache& render_pass_cache;
std::optional<ASTCDecoderPass> astc_decoder_pass; std::optional<ASTCDecoderPass> astc_decoder_pass;
std::optional<ASTCDecoderFragmentPass> astc_decoder_fragment_pass;
std::optional<BlockLinearUnswizzle3DPass> bl3d_unswizzle_pass; std::optional<BlockLinearUnswizzle3DPass> bl3d_unswizzle_pass;
const Settings::ResolutionScalingInfo& resolution; const Settings::ResolutionScalingInfo& resolution;
@@ -179,6 +178,8 @@ public:
std::span<ImageView*, NUM_RT> color_buffers, ImageView* depth_buffer, std::span<ImageView*, NUM_RT> color_buffers, ImageView* depth_buffer,
bool is_rescaled = false); bool is_rescaled = false);
void BeginRendering(vk::CommandBuffer cmdbuf) const;
[[nodiscard]] VkFramebuffer Handle() const noexcept { [[nodiscard]] VkFramebuffer Handle() const noexcept {
return *framebuffer; return *framebuffer;
} }
@@ -194,6 +195,39 @@ public:
[[nodiscard]] VkRenderPass RenderPassVariant(u32 color_clear_mask, bool depth_stencil_clear, [[nodiscard]] VkRenderPass RenderPassVariant(u32 color_clear_mask, bool depth_stencil_clear,
u32 color_discard_mask) const; u32 color_discard_mask) const;
[[nodiscard]] u32 NumColorAttachments() const noexcept {
return num_color_attachments;
}
[[nodiscard]] const std::array<VkImageView, NUM_RT>& ColorAttachments() const noexcept {
return color_attachments;
}
[[nodiscard]] const std::array<VkFormat, NUM_RT>& ColorAttachmentFormats() const noexcept {
return color_attachment_formats;
}
[[nodiscard]] const std::array<VkImageView, NUM_RT>& ColorResolveAttachments() const noexcept {
return color_resolve_attachments;
}
[[nodiscard]] const std::array<VkResolveModeFlagBits, NUM_RT>& ColorResolveModes()
const noexcept {
return color_resolve_modes;
}
[[nodiscard]] VkImageView DepthAttachment() const noexcept {
return depth_attachment;
}
[[nodiscard]] VkFormat DepthAttachmentFormat() const noexcept {
return depth_attachment_format;
}
[[nodiscard]] u32 NumLayers() const noexcept {
return layer_count;
}
[[nodiscard]] VkExtent2D RenderArea() const noexcept { [[nodiscard]] VkExtent2D RenderArea() const noexcept {
return render_area; return render_area;
} }
@@ -246,6 +280,10 @@ public:
return discard_msaa_color; return discard_msaa_color;
} }
[[nodiscard]] bool DiscardsMsaaDepth() const noexcept {
return discard_msaa_depth;
}
private: private:
vk::Framebuffer framebuffer; vk::Framebuffer framebuffer;
VkRenderPass renderpass{}; VkRenderPass renderpass{};
@@ -256,6 +294,14 @@ private:
std::array<VkImage, 9> images{}; std::array<VkImage, 9> images{};
std::array<VkImageSubresourceRange, 9> image_ranges{}; std::array<VkImageSubresourceRange, 9> image_ranges{};
std::array<size_t, NUM_RT> rt_map{}; std::array<size_t, NUM_RT> rt_map{};
std::array<VkImageView, NUM_RT> color_attachments{};
std::array<VkFormat, NUM_RT> color_attachment_formats{};
std::array<VkImageView, NUM_RT> color_resolve_attachments{};
std::array<VkResolveModeFlagBits, NUM_RT> color_resolve_modes{};
VkImageView depth_attachment{};
VkFormat depth_attachment_format = VK_FORMAT_UNDEFINED;
u32 num_color_attachments = 0;
u32 layer_count = 1;
bool has_depth{}; bool has_depth{};
bool has_stencil{}; bool has_stencil{};
bool is_rescaled{}; bool is_rescaled{};
@@ -264,6 +310,7 @@ private:
RenderPassKey render_pass_key{}; RenderPassKey render_pass_key{};
RenderPassCache* render_pass_cache{nullptr}; RenderPassCache* render_pass_cache{nullptr};
bool discard_msaa_color{}; bool discard_msaa_color{};
bool discard_msaa_depth{};
}; };
class Image : public VideoCommon::ImageBase { class Image : public VideoCommon::ImageBase {
+9 -10
View File
@@ -517,22 +517,16 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME); VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME);
LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken shader float controls."); LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken shader float controls.");
RemoveExtension(extensions.shader_float_controls, VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); RemoveExtension(extensions.shader_float_controls, VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken workgroup memory explicit layout.");
RemoveExtensionFeature(extensions.workgroup_memory_explicit_layout,
features.workgroup_memory_explicit_layout,
VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME);
LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken conservative rasterization.");
RemoveExtension(extensions.conservative_rasterization,
VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME);
LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken depth clip control.");
RemoveExtensionFeature(extensions.depth_clip_control, features.depth_clip_control,
VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken shader atomic int64."); LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken shader atomic int64.");
RemoveExtensionFeature(extensions.shader_atomic_int64, features.shader_atomic_int64, RemoveExtensionFeature(extensions.shader_atomic_int64, features.shader_atomic_int64,
VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME); VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME);
features.shader_atomic_int64.shaderBufferInt64Atomics = false; features.shader_atomic_int64.shaderBufferInt64Atomics = false;
features.shader_atomic_int64.shaderSharedInt64Atomics = false; features.shader_atomic_int64.shaderSharedInt64Atomics = false;
features.features.shaderInt64 = false; features.features.shaderInt64 = false;
LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken workgroup memory explicit layout.");
RemoveExtensionFeature(extensions.workgroup_memory_explicit_layout,
features.workgroup_memory_explicit_layout,
VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME);
#if defined(__ANDROID__) && defined(ARCHITECTURE_arm64) #if defined(__ANDROID__) && defined(ARCHITECTURE_arm64)
// BCn patching only safe on Android 9+ (API 28+). Older versions crash on driver load. // BCn patching only safe on Android 9+ (API 28+). Older versions crash on driver load.
@@ -1379,6 +1373,11 @@ void Device::RemoveUnsuitableExtensions() {
extensions.maintenance3 = loaded_extensions.contains(VK_KHR_MAINTENANCE_3_EXTENSION_NAME); extensions.maintenance3 = loaded_extensions.contains(VK_KHR_MAINTENANCE_3_EXTENSION_NAME);
RemoveExtensionIfUnsuitable(extensions.maintenance3, VK_KHR_MAINTENANCE_3_EXTENSION_NAME); RemoveExtensionIfUnsuitable(extensions.maintenance3, VK_KHR_MAINTENANCE_3_EXTENSION_NAME);
// VK_KHR_dynamic_rendering
extensions.dynamic_rendering = features.dynamic_rendering.dynamicRendering;
RemoveExtensionFeatureIfUnsuitable(extensions.dynamic_rendering, features.dynamic_rendering,
VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
// VK_KHR_maintenance4 // VK_KHR_maintenance4
extensions.maintenance4 = features.maintenance4.maintenance4; extensions.maintenance4 = features.maintenance4.maintenance4;
RemoveExtensionFeatureIfUnsuitable(extensions.maintenance4, features.maintenance4, RemoveExtensionFeatureIfUnsuitable(extensions.maintenance4, features.maintenance4,
@@ -43,6 +43,7 @@ VK_DEFINE_HANDLE(VmaAllocator)
FEATURE(EXT, ShaderDemoteToHelperInvocation, SHADER_DEMOTE_TO_HELPER_INVOCATION, \ FEATURE(EXT, ShaderDemoteToHelperInvocation, SHADER_DEMOTE_TO_HELPER_INVOCATION, \
shader_demote_to_helper_invocation) \ shader_demote_to_helper_invocation) \
FEATURE(EXT, SubgroupSizeControl, SUBGROUP_SIZE_CONTROL, subgroup_size_control) \ FEATURE(EXT, SubgroupSizeControl, SUBGROUP_SIZE_CONTROL, subgroup_size_control) \
FEATURE(KHR, DynamicRendering, DYNAMIC_RENDERING, dynamic_rendering) \
FEATURE(KHR, Maintenance4, MAINTENANCE_4, maintenance4) \ FEATURE(KHR, Maintenance4, MAINTENANCE_4, maintenance4) \
FEATURE(KHR, Synchronization2, SYNCHRONIZATION_2, synchronization2) FEATURE(KHR, Synchronization2, SYNCHRONIZATION_2, synchronization2)
@@ -941,6 +942,13 @@ FN_MAX_LIMIT_LIST
return extensions.maintenance3; return extensions.maintenance3;
} }
static constexpr bool ENABLE_DYNAMIC_RENDERING = false;
/// Returns true if the device supports VK_KHR_dynamic_rendering.
bool IsKhrDynamicRenderingSupported() const {
return ENABLE_DYNAMIC_RENDERING && extensions.dynamic_rendering;
}
/// Returns true if the device supports VK_KHR_maintenance4. /// Returns true if the device supports VK_KHR_maintenance4.
bool IsKhrMaintenance4Supported() const { bool IsKhrMaintenance4Supported() const {
return extensions.maintenance4; return extensions.maintenance4;
@@ -92,6 +92,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkCmdBeginConditionalRenderingEXT); X(vkCmdBeginConditionalRenderingEXT);
X(vkCmdBeginQuery); X(vkCmdBeginQuery);
X(vkCmdBeginRenderPass); X(vkCmdBeginRenderPass);
X(vkCmdBeginRendering);
X(vkCmdBeginTransformFeedbackEXT); X(vkCmdBeginTransformFeedbackEXT);
X(vkCmdBeginDebugUtilsLabelEXT); X(vkCmdBeginDebugUtilsLabelEXT);
X(vkCmdBindDescriptorSets); X(vkCmdBindDescriptorSets);
@@ -119,6 +120,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkCmdEndConditionalRenderingEXT); X(vkCmdEndConditionalRenderingEXT);
X(vkCmdEndQuery); X(vkCmdEndQuery);
X(vkCmdEndRenderPass); X(vkCmdEndRenderPass);
X(vkCmdEndRendering);
X(vkCmdEndTransformFeedbackEXT); X(vkCmdEndTransformFeedbackEXT);
X(vkCmdEndDebugUtilsLabelEXT); X(vkCmdEndDebugUtilsLabelEXT);
X(vkCmdFillBuffer); X(vkCmdFillBuffer);
@@ -258,6 +260,12 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
Proc(dld.vkCmdDrawIndexedIndirectCount, dld, "vkCmdDrawIndexedIndirectCountKHR", device); Proc(dld.vkCmdDrawIndexedIndirectCount, dld, "vkCmdDrawIndexedIndirectCountKHR", device);
} }
// Support for dynamic rendering is optional until Vulkan 1.3
if (!dld.vkCmdBeginRendering) {
Proc(dld.vkCmdBeginRendering, dld, "vkCmdBeginRenderingKHR", device);
Proc(dld.vkCmdEndRendering, dld, "vkCmdEndRenderingKHR", device);
}
// Synchronization2 is core in Vulkan 1.3, otherwise requires VK_KHR_synchronization2 // Synchronization2 is core in Vulkan 1.3, otherwise requires VK_KHR_synchronization2
if (!dld.vkCmdPipelineBarrier2) { if (!dld.vkCmdPipelineBarrier2) {
Proc(dld.vkCmdPipelineBarrier2, dld, "vkCmdPipelineBarrier2KHR", device); Proc(dld.vkCmdPipelineBarrier2, dld, "vkCmdPipelineBarrier2KHR", device);
@@ -208,6 +208,7 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT{}; PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT{};
PFN_vkCmdBeginQuery vkCmdBeginQuery{}; PFN_vkCmdBeginQuery vkCmdBeginQuery{};
PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass{}; PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass{};
PFN_vkCmdBeginRendering vkCmdBeginRendering{};
PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT{}; PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT{};
PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets{}; PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets{};
PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer{}; PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer{};
@@ -236,6 +237,7 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT{}; PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT{};
PFN_vkCmdEndQuery vkCmdEndQuery{}; PFN_vkCmdEndQuery vkCmdEndQuery{};
PFN_vkCmdEndRenderPass vkCmdEndRenderPass{}; PFN_vkCmdEndRenderPass vkCmdEndRenderPass{};
PFN_vkCmdEndRendering vkCmdEndRendering{};
PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT{}; PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT{};
PFN_vkCmdFillBuffer vkCmdFillBuffer{}; PFN_vkCmdFillBuffer vkCmdFillBuffer{};
PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier{}; PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier{};
@@ -1191,6 +1193,14 @@ public:
dld->vkCmdEndRenderPass(handle); dld->vkCmdEndRenderPass(handle);
} }
void BeginRendering(const VkRenderingInfo& rendering_info) const noexcept {
dld->vkCmdBeginRendering(handle, &rendering_info);
}
void EndRendering() const noexcept {
dld->vkCmdEndRendering(handle);
}
void BeginQuery(VkQueryPool query_pool, u32 query, VkQueryControlFlags flags) const noexcept { void BeginQuery(VkQueryPool query_pool, u32 query, VkQueryControlFlags flags) const noexcept {
dld->vkCmdBeginQuery(handle, query_pool, query, flags); dld->vkCmdBeginQuery(handle, query_pool, query, flags);
} }