mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-26 09:06:45 +00:00
[TEST] Add XFB binding
This commit is contained in:
@@ -1254,17 +1254,73 @@ void BufferCache<P>::BindHostTransformFeedbackBuffers() {
|
||||
if (maxwell3d->regs.transform_feedback_enabled == 0) {
|
||||
return;
|
||||
}
|
||||
HostBindings<typename P::Buffer> host_bindings;
|
||||
for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) {
|
||||
const auto is_active = [&](u32 index) {
|
||||
const Binding& binding = channel_state->transform_feedback_buffers[index];
|
||||
const auto& control = maxwell3d->regs.transform_feedback.controls[index];
|
||||
const bool has_layout = control.varying_count != 0 || control.stride != 0;
|
||||
return has_layout && binding.buffer_id != NULL_BUFFER_ID && binding.size != 0;
|
||||
};
|
||||
|
||||
std::array<u64, NUM_TRANSFORM_FEEDBACK_BUFFERS> window_indices{};
|
||||
std::array<u64, NUM_TRANSFORM_FEEDBACK_BUFFERS> window_offsets{};
|
||||
u32 window_mask = 0;
|
||||
if constexpr (USE_UNIFIED_DIRECT_BINDING) {
|
||||
if (runtime.SupportsUnifiedTransformFeedbackBinding()) {
|
||||
for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) {
|
||||
if (!is_active(index)) {
|
||||
continue;
|
||||
}
|
||||
const Binding& binding = channel_state->transform_feedback_buffers[index];
|
||||
if (binding.size > runtime.UnifiedMaxTransformFeedbackBufferSize()) {
|
||||
continue;
|
||||
}
|
||||
if (ResolveUnifiedDirectBinding(binding.device_addr, binding.size,
|
||||
UNIFIED_TRANSFORM_FEEDBACK_BINDING_ALIGNMENT,
|
||||
window_indices[index], window_offsets[index])) {
|
||||
window_mask |= 1u << index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (USE_UNIFIED_DIRECT_BINDING) {
|
||||
if (window_mask != 0) {
|
||||
for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) {
|
||||
const Binding& binding = channel_state->transform_feedback_buffers[index];
|
||||
if (((window_mask >> index) & 1) != 0) {
|
||||
TouchBuffer(slot_buffers[binding.buffer_id], binding.buffer_id);
|
||||
MarkWrittenBufferInPlace(binding.device_addr, binding.size);
|
||||
runtime.BindTransformFeedbackBufferFromWindow(
|
||||
index, window_indices[index], static_cast<u32>(window_offsets[index]),
|
||||
binding.size);
|
||||
continue;
|
||||
}
|
||||
if (!is_active(index)) {
|
||||
runtime.BindNullTransformFeedbackBuffer(index);
|
||||
continue;
|
||||
}
|
||||
Buffer& buffer = slot_buffers[binding.buffer_id];
|
||||
TouchBuffer(buffer, binding.buffer_id);
|
||||
const u32 size = binding.size;
|
||||
SynchronizeBuffer(buffer, binding.device_addr, size);
|
||||
MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
|
||||
const u32 offset = buffer.Offset(binding.device_addr);
|
||||
buffer.MarkUsage(offset, size);
|
||||
runtime.BindTransformFeedbackBuffer(index, buffer, offset, size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
HostBindings<typename P::Buffer> host_bindings;
|
||||
for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) {
|
||||
const Binding& binding = channel_state->transform_feedback_buffers[index];
|
||||
|
||||
Buffer* host_buffer = &slot_buffers[NULL_BUFFER_ID];
|
||||
u32 offset = 0;
|
||||
u32 size = 0;
|
||||
|
||||
if (has_layout && binding.buffer_id != NULL_BUFFER_ID && binding.size != 0) {
|
||||
if (is_active(index)) {
|
||||
Buffer& buffer = slot_buffers[binding.buffer_id];
|
||||
TouchBuffer(buffer, binding.buffer_id);
|
||||
size = binding.size;
|
||||
|
||||
@@ -184,6 +184,7 @@ class BufferCache : public VideoCommon::ChannelSetupCaches<BufferCacheChannelInf
|
||||
static constexpr bool USE_UNIFIED_UPLOADS = P::USE_UNIFIED_UPLOADS;
|
||||
static constexpr bool USE_UNIFIED_DIRECT_BINDING = P::USE_UNIFIED_DIRECT_BINDING;
|
||||
static constexpr u64 UNIFIED_VERTEX_BINDING_ALIGNMENT = 4;
|
||||
static constexpr u64 UNIFIED_TRANSFORM_FEEDBACK_BINDING_ALIGNMENT = 4;
|
||||
|
||||
#ifdef YUZU_LEGACY
|
||||
static constexpr s64 TARGET_THRESHOLD = 3_GiB;
|
||||
|
||||
@@ -492,16 +492,20 @@ void BufferCacheRuntime::UnifiedMemoryHostBarrier() {
|
||||
}
|
||||
|
||||
void BufferCacheRuntime::UnifiedMemoryShaderWriteBarrier() {
|
||||
static constexpr VkMemoryBarrier SHADER_WRITE_BARRIER{
|
||||
const bool has_transform_feedback = device.IsExtTransformFeedbackSupported();
|
||||
const VkMemoryBarrier write_barrier{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
|
||||
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT |
|
||||
(has_transform_feedback ? VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT : 0),
|
||||
.dstAccessMask = VK_ACCESS_HOST_READ_BIT,
|
||||
};
|
||||
const VkPipelineStageFlags src_stages =
|
||||
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE |
|
||||
(has_transform_feedback ? VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT : 0);
|
||||
scheduler.RequestOutsideRenderPassOperationContext();
|
||||
scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, VK_PIPELINE_STAGE_HOST_BIT, 0,
|
||||
SHADER_WRITE_BARRIER);
|
||||
scheduler.Record([write_barrier, src_stages](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.PipelineBarrier(src_stages, VK_PIPELINE_STAGE_HOST_BIT, 0, write_barrier);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -170,6 +170,23 @@ public:
|
||||
return device.GetTexelBufferAlignment();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool SupportsUnifiedTransformFeedbackBinding() const noexcept {
|
||||
return SupportsUnifiedDirectBinding() && device.IsExtTransformFeedbackSupported();
|
||||
}
|
||||
|
||||
[[nodiscard]] u64 UnifiedMaxTransformFeedbackBufferSize() const noexcept {
|
||||
return device.GetMaxTransformFeedbackBufferSize();
|
||||
}
|
||||
|
||||
void BindTransformFeedbackBufferFromWindow(u32 index, size_t window_index, u32 offset,
|
||||
u32 size) {
|
||||
BindTransformFeedbackBuffer(index, UnifiedWindowBuffer(window_index), offset, size);
|
||||
}
|
||||
|
||||
void BindNullTransformFeedbackBuffer(u32 index) {
|
||||
BindTransformFeedbackBuffer(index, VK_NULL_HANDLE, 0, 0);
|
||||
}
|
||||
|
||||
void BindBufferFromWindow(size_t window_index, u32 offset, u32 size) {
|
||||
guest_descriptor_queue.AddBuffer(UnifiedWindowBuffer(window_index),
|
||||
UnifiedWindowAddress(window_index), offset, size);
|
||||
|
||||
@@ -352,11 +352,17 @@ public:
|
||||
return properties.properties.limits.maxUniformBufferRange;
|
||||
}
|
||||
|
||||
/// Returns texel buffer alignment requirement.
|
||||
/// Returns transform feedback buffer alignment requirement.
|
||||
VkDeviceSize GetMaxTransformFeedbackBufferSize() const {
|
||||
return properties.transform_feedback.maxTransformFeedbackBufferSize;
|
||||
}
|
||||
|
||||
// Returns texel buffer alignment requirement.
|
||||
VkDeviceSize GetTexelBufferAlignment() const {
|
||||
return properties.properties.limits.minTexelBufferOffsetAlignment;
|
||||
}
|
||||
|
||||
/// Returns the maximum number of workgroups that can be dispatched in a single dimension.
|
||||
std::array<u32, 3> GetMaxComputeWorkGroupCount() const {
|
||||
const auto& count = properties.properties.limits.maxComputeWorkGroupCount;
|
||||
return {count[0], count[1], count[2]};
|
||||
|
||||
Reference in New Issue
Block a user