Browse Source

[TEST] Adjustments on descriptors payloads

vk-experiments9
CamilleLaVey 5 days ago
parent
commit
0408db7adb
  1. 5
      src/shader_recompiler/environment.h
  2. 2
      src/shader_recompiler/ir_opt/texture_pass.cpp
  3. 13
      src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
  4. 3
      src/video_core/renderer_vulkan/vk_rasterizer.cpp
  5. 19
      src/video_core/renderer_vulkan/vk_update_descriptor.cpp
  6. 12
      src/video_core/renderer_vulkan/vk_update_descriptor.h
  7. 46
      src/video_core/shader_environment.cpp
  8. 5
      src/video_core/shader_environment.h

5
src/shader_recompiler/environment.h

@ -78,6 +78,11 @@ public:
[[nodiscard]] virtual TextureType ReadTextureType(u32 raw_handle) = 0;
[[nodiscard]] virtual u32 ResolveBindlessHandle(u32 cbuf_index, u32 cbuf_offset,
u32 raw_handle) {
return raw_handle;
}
[[nodiscard]] virtual TexturePixelFormat ReadTexturePixelFormat(u32 raw_handle) = 0;
[[nodiscard]] virtual bool IsTexturePixelFormatInteger(u32 raw_handle) = 0;

2
src/shader_recompiler/ir_opt/texture_pass.cpp

@ -502,7 +502,7 @@ u32 GetTextureHandle(Environment& env, const ConstBufferAddr& cbuf) {
const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset) << cbuf.shift_left};
const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset)
<< cbuf.secondary_shift_left};
return lhs_raw | rhs_raw;
return env.ResolveBindlessHandle(cbuf.index, cbuf.offset, lhs_raw | rhs_raw);
}
[[maybe_unused]] TextureType ReadTextureType(Environment& env, const ConstBufferAddr& cbuf) {

13
src/video_core/renderer_vulkan/vk_compute_pipeline.cpp

@ -18,6 +18,7 @@
#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
#include "video_core/shader_environment.h"
#include "video_core/shader_notify.h"
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
@ -148,6 +149,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
const auto& qmd{kepler_compute.launch_description};
const auto& cbufs{qmd.const_buffer_config};
const bool via_header_index{qmd.linked_tsc != 0};
const u32 tic_limit{kepler_compute.regs.tic.limit};
const auto read_handle{[&](const auto& desc, u32 index) {
ASSERT(((qmd.const_buffer_enable_mask >> desc.cbuf_index) & 1) != 0);
const u32 index_offset{index << desc.size_shift};
@ -162,10 +164,17 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
secondary_offset};
const u32 lhs_raw{gpu_memory.Read<u32>(addr) << desc.shift_left};
const u32 rhs_raw{gpu_memory.Read<u32>(separate_addr) << desc.secondary_shift_left};
return TexturePair(lhs_raw | rhs_raw, via_header_index);
const u32 combined{VideoCommon::ResolveBindlessHandleTable(
gpu_memory, addr, lhs_raw | rhs_raw,
TexturePair(lhs_raw | rhs_raw, via_header_index).first, tic_limit)};
return TexturePair(combined, via_header_index);
}
}
return TexturePair(gpu_memory.Read<u32>(addr), via_header_index);
const u32 single_raw{gpu_memory.Read<u32>(addr)};
return TexturePair(VideoCommon::ResolveBindlessHandleTable(
gpu_memory, addr, single_raw,
TexturePair(single_raw, via_header_index).first, tic_limit),
via_header_index);
}};
const auto add_image{[&](const auto& desc, bool blacklist) {
for (u32 index = 0; index < desc.count; ++index) {

3
src/video_core/renderer_vulkan/vk_rasterizer.cpp

@ -203,7 +203,8 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra
: gpu{gpu_}, device_memory{device_memory_}, device{device_},
memory_allocator{memory_allocator_}, state_tracker{state_tracker_}, scheduler{scheduler_},
staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler),
guest_descriptor_queue(device), compute_pass_descriptor_queue(device),
guest_descriptor_queue(device, UpdateDescriptorQueue::GUEST_FRAME_PAYLOAD_SIZE),
compute_pass_descriptor_queue(device, UpdateDescriptorQueue::COMPUTE_FRAME_PAYLOAD_SIZE),
blit_image(device, scheduler, state_tracker, descriptor_pool), render_pass_cache(device),
texture_cache_runtime{
device, scheduler, memory_allocator, staging_pool,

19
src/video_core/renderer_vulkan/vk_update_descriptor.cpp

@ -16,11 +16,12 @@
namespace Vulkan {
UpdateDescriptorQueue::UpdateDescriptorQueue(const Device& device_)
: device{device_}
UpdateDescriptorQueue::UpdateDescriptorQueue(const Device& device_, size_t frame_payload_size_)
: device{device_}, frame_payload_size{frame_payload_size_},
payload{std::make_unique<DescriptorUpdateEntry[]>(frame_payload_size_ * FRAMES_IN_FLIGHT)}
{
payload_start = payload.data();
payload_cursor = payload.data();
payload_start = payload.get();
payload_cursor = payload.get();
}
UpdateDescriptorQueue::~UpdateDescriptorQueue() = default;
@ -29,19 +30,19 @@ void UpdateDescriptorQueue::TickFrame() {
if (++frame_index >= FRAMES_IN_FLIGHT) {
frame_index = 0;
}
payload_start = payload.data() + frame_index * FRAME_PAYLOAD_SIZE;
payload_start = payload.get() + frame_index * frame_payload_size;
payload_cursor = payload_start;
}
void UpdateDescriptorQueue::Acquire(Scheduler& scheduler, size_t required_entries) {
static constexpr size_t DEFAULT_REQUIRED_ENTRIES = 0x400;
const size_t reserve = required_entries > 0 ? required_entries : DEFAULT_REQUIRED_ENTRIES;
ASSERT_MSG(reserve < FRAME_PAYLOAD_SIZE, "Descriptor reservation {} >= frame capacity {}",
reserve, FRAME_PAYLOAD_SIZE);
ASSERT_MSG(reserve < frame_payload_size, "Descriptor reservation {} >= frame capacity {}",
reserve, frame_payload_size);
const size_t used = static_cast<size_t>(std::distance(payload_start, payload_cursor));
if (used + reserve >= FRAME_PAYLOAD_SIZE) {
if (used + reserve >= frame_payload_size) {
LOG_WARNING(Render_Vulkan, "Payload overflow (used={}, reserve={}, capacity={})",
used, reserve, FRAME_PAYLOAD_SIZE);
used, reserve, frame_payload_size);
scheduler.WaitWorker();
payload_cursor = payload_start;
}

12
src/video_core/renderer_vulkan/vk_update_descriptor.h

@ -6,7 +6,7 @@
#pragma once
#include <array>
#include <memory>
#include <variant>
#include "video_core/vulkan_common/vulkan_wrapper.h"
@ -30,11 +30,12 @@ class UpdateDescriptorQueue final {
// This should be plenty for the vast majority of cases. Most desktop platforms only
// provide up to 3 swapchain images.
static constexpr size_t FRAMES_IN_FLIGHT = 8;
static constexpr size_t FRAME_PAYLOAD_SIZE = 0x40000;
static constexpr size_t PAYLOAD_SIZE = FRAME_PAYLOAD_SIZE * FRAMES_IN_FLIGHT;
public:
explicit UpdateDescriptorQueue(const Device& device_);
static constexpr size_t GUEST_FRAME_PAYLOAD_SIZE = 0x80000;
static constexpr size_t COMPUTE_FRAME_PAYLOAD_SIZE = 0x20000;
explicit UpdateDescriptorQueue(const Device& device_, size_t frame_payload_size_);
~UpdateDescriptorQueue();
void TickFrame();
@ -74,11 +75,12 @@ public:
private:
const Device& device;
const size_t frame_payload_size;
size_t frame_index{0};
DescriptorUpdateEntry* payload_cursor = nullptr;
DescriptorUpdateEntry* payload_start = nullptr;
const DescriptorUpdateEntry* upload_start = nullptr;
std::array<DescriptorUpdateEntry, PAYLOAD_SIZE> payload;
std::unique_ptr<DescriptorUpdateEntry[]> payload;
};
// TODO: should these be separate classes instead?

46
src/video_core/shader_environment.cpp

@ -281,6 +281,34 @@ std::optional<u64> GenericEnvironment::TryFindSize() {
return std::nullopt;
}
u32 ResolveBindlessHandleTable(Tegra::MemoryManager& gpu_memory, GPUVAddr record_addr,
u32 raw_handle, u32 tic_index, u32 tic_limit) {
static constexpr u32 HandleRecordSize = 16;
static constexpr u32 MaxHandleTableBytes = 64 * 1024;
if (tic_index <= tic_limit) {
return raw_handle;
}
const u32 addr_low{gpu_memory.Read<u32>(record_addr)};
const u32 addr_high{gpu_memory.Read<u32>(record_addr + 4)};
const u32 table_size{gpu_memory.Read<u32>(record_addr + 8)};
const GPUVAddr table_addr{(static_cast<GPUVAddr>(addr_high) << 32) |
static_cast<GPUVAddr>(addr_low)};
if (table_addr == 0 || table_size < HandleRecordSize || table_size > MaxHandleTableBytes) {
return raw_handle;
}
const u32 count{table_size / HandleRecordSize};
for (u32 i = 0; i < count; ++i) {
const GPUVAddr entry_addr{table_addr + static_cast<GPUVAddr>(i) * HandleRecordSize};
const u32 handle{gpu_memory.Read<u32>(entry_addr)};
const u32 live{gpu_memory.Read<u32>(entry_addr + 4)};
if (live != 0 && handle != 0 && handle <= tic_limit) {
return handle;
}
}
return raw_handle;
}
Tegra::Texture::TICEntry GenericEnvironment::ReadTextureInfo(GPUVAddr tic_addr, u32 tic_limit,
bool via_header_index, u32 raw) {
const auto handle{Tegra::Texture::TexturePair(raw, via_header_index)};
@ -431,6 +459,24 @@ u32 ComputeEnvironment::ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) {
return value;
}
u32 ComputeEnvironment::ResolveBindlessHandle(u32 cbuf_index, u32 cbuf_offset, u32 raw_handle) {
const auto& regs{kepler_compute->regs};
const auto& qmd{kepler_compute->launch_description};
const auto pair{Tegra::Texture::TexturePair(raw_handle, qmd.linked_tsc != 0)};
if (pair.first <= regs.tic.limit) {
return raw_handle;
}
if (((qmd.const_buffer_enable_mask.Value() >> cbuf_index) & 1) == 0) {
return raw_handle;
}
const auto& cbuf{qmd.const_buffer_config[cbuf_index]};
if (cbuf_offset + 12 > cbuf.size) {
return raw_handle;
}
return ResolveBindlessHandleTable(*gpu_memory, cbuf.Address() + cbuf_offset, raw_handle,
pair.first, regs.tic.limit);
}
Shader::TextureType ComputeEnvironment::ReadTextureType(u32 handle) {
const auto& regs{kepler_compute->regs};
const auto& qmd{kepler_compute->launch_description};

5
src/video_core/shader_environment.h

@ -29,6 +29,9 @@ class Memorymanager;
namespace VideoCommon {
[[nodiscard]] u32 ResolveBindlessHandleTable(Tegra::MemoryManager& gpu_memory, GPUVAddr record_addr,
u32 raw_handle, u32 tic_index, u32 tic_limit);
class GenericEnvironment : public Shader::Environment {
public:
explicit GenericEnvironment() = default;
@ -140,6 +143,8 @@ public:
u32 ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) override;
u32 ResolveBindlessHandle(u32 cbuf_index, u32 cbuf_offset, u32 raw_handle) override;
Shader::TextureType ReadTextureType(u32 handle) override;
Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override;

Loading…
Cancel
Save