video_core: Abstract transform feedback translation utility
This commit is contained in:
		@@ -187,6 +187,8 @@ add_library(video_core STATIC
 | 
			
		||||
    textures/decoders.h
 | 
			
		||||
    textures/texture.cpp
 | 
			
		||||
    textures/texture.h
 | 
			
		||||
    transform_feedback.cpp
 | 
			
		||||
    transform_feedback.h
 | 
			
		||||
    video_core.cpp
 | 
			
		||||
    video_core.h
 | 
			
		||||
    vulkan_common/vulkan_debug_callback.cpp
 | 
			
		||||
 
 | 
			
		||||
@@ -15,9 +15,7 @@
 | 
			
		||||
#include "video_core/renderer_vulkan/vk_state_tracker.h"
 | 
			
		||||
 | 
			
		||||
namespace Vulkan {
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
constexpr size_t POINT = 0;
 | 
			
		||||
constexpr size_t LINE = 1;
 | 
			
		||||
constexpr size_t POLYGON = 2;
 | 
			
		||||
@@ -39,6 +37,16 @@ constexpr std::array POLYGON_OFFSET_ENABLE_LUT = {
 | 
			
		||||
    POLYGON, // Patches
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void RefreshXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs) {
 | 
			
		||||
    std::ranges::transform(regs.tfb_layouts, state.layouts.begin(), [](const auto& layout) {
 | 
			
		||||
        return VideoCommon::TransformFeedbackState::Layout{
 | 
			
		||||
            .stream = layout.stream,
 | 
			
		||||
            .varying_count = layout.varying_count,
 | 
			
		||||
            .stride = layout.stride,
 | 
			
		||||
        };
 | 
			
		||||
    });
 | 
			
		||||
    state.varyings = regs.tfb_varying_locs;
 | 
			
		||||
}
 | 
			
		||||
} // Anonymous namespace
 | 
			
		||||
 | 
			
		||||
void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d,
 | 
			
		||||
@@ -121,7 +129,7 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d,
 | 
			
		||||
        dynamic_state.Refresh(regs);
 | 
			
		||||
    }
 | 
			
		||||
    if (xfb_enabled != 0) {
 | 
			
		||||
        xfb_state.Refresh(regs);
 | 
			
		||||
        RefreshXfbState(xfb_state, regs);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -164,17 +172,6 @@ void FixedPipelineState::BlendingAttachment::Refresh(const Maxwell& regs, size_t
 | 
			
		||||
    enable.Assign(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FixedPipelineState::TransformFeedbackState::Refresh(const Maxwell& regs) {
 | 
			
		||||
    std::ranges::transform(regs.tfb_layouts, layouts.begin(), [](const auto& layout) {
 | 
			
		||||
        return Layout{
 | 
			
		||||
            .stream = layout.stream,
 | 
			
		||||
            .varying_count = layout.varying_count,
 | 
			
		||||
            .stride = layout.stride,
 | 
			
		||||
        };
 | 
			
		||||
    });
 | 
			
		||||
    varyings = regs.tfb_varying_locs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FixedPipelineState::DynamicState::Refresh(const Maxwell& regs) {
 | 
			
		||||
    u32 packed_front_face = PackFrontFace(regs.front_face);
 | 
			
		||||
    if (regs.screen_y_control.triangle_rast_flip != 0) {
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@
 | 
			
		||||
 | 
			
		||||
#include "video_core/engines/maxwell_3d.h"
 | 
			
		||||
#include "video_core/surface.h"
 | 
			
		||||
#include "video_core/transform_feedback.h"
 | 
			
		||||
 | 
			
		||||
namespace Vulkan {
 | 
			
		||||
 | 
			
		||||
@@ -130,18 +131,6 @@ struct FixedPipelineState {
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct TransformFeedbackState {
 | 
			
		||||
        struct Layout {
 | 
			
		||||
            u32 stream;
 | 
			
		||||
            u32 varying_count;
 | 
			
		||||
            u32 stride;
 | 
			
		||||
        };
 | 
			
		||||
        std::array<Layout, Maxwell::NumTransformFeedbackBuffers> layouts;
 | 
			
		||||
        std::array<std::array<u8, 128>, Maxwell::NumTransformFeedbackBuffers> varyings;
 | 
			
		||||
 | 
			
		||||
        void Refresh(const Maxwell& regs);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct DynamicState {
 | 
			
		||||
        union {
 | 
			
		||||
            u32 raw1;
 | 
			
		||||
@@ -213,7 +202,7 @@ struct FixedPipelineState {
 | 
			
		||||
    std::array<BlendingAttachment, Maxwell::NumRenderTargets> attachments;
 | 
			
		||||
    std::array<u16, Maxwell::NumViewports> viewport_swizzles;
 | 
			
		||||
    DynamicState dynamic_state;
 | 
			
		||||
    TransformFeedbackState xfb_state;
 | 
			
		||||
    VideoCommon::TransformFeedbackState xfb_state;
 | 
			
		||||
 | 
			
		||||
    void Refresh(Tegra::Engines::Maxwell3D& maxwell3d, bool has_extended_dynamic_state);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -109,88 +109,6 @@ static Shader::AttributeType CastAttributeType(const FixedPipelineState::VertexA
 | 
			
		||||
    return Shader::AttributeType::Float;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<Shader::TransformFeedbackVarying> MakeTransformFeedbackVaryings(
 | 
			
		||||
    const GraphicsPipelineCacheKey& key) {
 | 
			
		||||
    static constexpr std::array VECTORS{
 | 
			
		||||
        28,  // gl_Position
 | 
			
		||||
        32,  // Generic 0
 | 
			
		||||
        36,  // Generic 1
 | 
			
		||||
        40,  // Generic 2
 | 
			
		||||
        44,  // Generic 3
 | 
			
		||||
        48,  // Generic 4
 | 
			
		||||
        52,  // Generic 5
 | 
			
		||||
        56,  // Generic 6
 | 
			
		||||
        60,  // Generic 7
 | 
			
		||||
        64,  // Generic 8
 | 
			
		||||
        68,  // Generic 9
 | 
			
		||||
        72,  // Generic 10
 | 
			
		||||
        76,  // Generic 11
 | 
			
		||||
        80,  // Generic 12
 | 
			
		||||
        84,  // Generic 13
 | 
			
		||||
        88,  // Generic 14
 | 
			
		||||
        92,  // Generic 15
 | 
			
		||||
        96,  // Generic 16
 | 
			
		||||
        100, // Generic 17
 | 
			
		||||
        104, // Generic 18
 | 
			
		||||
        108, // Generic 19
 | 
			
		||||
        112, // Generic 20
 | 
			
		||||
        116, // Generic 21
 | 
			
		||||
        120, // Generic 22
 | 
			
		||||
        124, // Generic 23
 | 
			
		||||
        128, // Generic 24
 | 
			
		||||
        132, // Generic 25
 | 
			
		||||
        136, // Generic 26
 | 
			
		||||
        140, // Generic 27
 | 
			
		||||
        144, // Generic 28
 | 
			
		||||
        148, // Generic 29
 | 
			
		||||
        152, // Generic 30
 | 
			
		||||
        156, // Generic 31
 | 
			
		||||
        160, // gl_FrontColor
 | 
			
		||||
        164, // gl_FrontSecondaryColor
 | 
			
		||||
        160, // gl_BackColor
 | 
			
		||||
        164, // gl_BackSecondaryColor
 | 
			
		||||
        192, // gl_TexCoord[0]
 | 
			
		||||
        196, // gl_TexCoord[1]
 | 
			
		||||
        200, // gl_TexCoord[2]
 | 
			
		||||
        204, // gl_TexCoord[3]
 | 
			
		||||
        208, // gl_TexCoord[4]
 | 
			
		||||
        212, // gl_TexCoord[5]
 | 
			
		||||
        216, // gl_TexCoord[6]
 | 
			
		||||
        220, // gl_TexCoord[7]
 | 
			
		||||
    };
 | 
			
		||||
    std::vector<Shader::TransformFeedbackVarying> xfb(256);
 | 
			
		||||
    for (size_t buffer = 0; buffer < Maxwell::NumTransformFeedbackBuffers; ++buffer) {
 | 
			
		||||
        const auto& locations = key.state.xfb_state.varyings[buffer];
 | 
			
		||||
        const auto& layout = key.state.xfb_state.layouts[buffer];
 | 
			
		||||
        const u32 varying_count = layout.varying_count;
 | 
			
		||||
        u32 highest = 0;
 | 
			
		||||
        for (u32 offset = 0; offset < varying_count; ++offset) {
 | 
			
		||||
            const u32 base_offset = offset;
 | 
			
		||||
            const u8 location = locations[offset];
 | 
			
		||||
 | 
			
		||||
            Shader::TransformFeedbackVarying varying;
 | 
			
		||||
            varying.buffer = layout.stream;
 | 
			
		||||
            varying.stride = layout.stride;
 | 
			
		||||
            varying.offset = offset * 4;
 | 
			
		||||
            varying.components = 1;
 | 
			
		||||
 | 
			
		||||
            if (std::ranges::find(VECTORS, Common::AlignDown(location, 4)) != VECTORS.end()) {
 | 
			
		||||
                UNIMPLEMENTED_IF_MSG(location % 4 != 0, "Unaligned TFB");
 | 
			
		||||
 | 
			
		||||
                const u8 base_index = location / 4;
 | 
			
		||||
                while (offset + 1 < varying_count && base_index == locations[offset + 1] / 4) {
 | 
			
		||||
                    ++offset;
 | 
			
		||||
                    ++varying.components;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            xfb[location] = varying;
 | 
			
		||||
            highest = std::max(highest, (base_offset + varying.components) * 4);
 | 
			
		||||
        }
 | 
			
		||||
        UNIMPLEMENTED_IF(highest != layout.stride);
 | 
			
		||||
    }
 | 
			
		||||
    return xfb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineCacheKey& key,
 | 
			
		||||
                                    const Shader::IR::Program& program) {
 | 
			
		||||
    Shader::RuntimeInfo info;
 | 
			
		||||
@@ -206,7 +124,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineCacheKey& key,
 | 
			
		||||
                info.fixed_state_point_size = point_size;
 | 
			
		||||
            }
 | 
			
		||||
            if (key.state.xfb_enabled != 0) {
 | 
			
		||||
                info.xfb_varyings = MakeTransformFeedbackVaryings(key);
 | 
			
		||||
                info.xfb_varyings = VideoCommon::MakeTransformFeedbackVaryings(key.state.xfb_state);
 | 
			
		||||
            }
 | 
			
		||||
            info.convert_depth_mode = gl_ndc;
 | 
			
		||||
        }
 | 
			
		||||
@@ -248,7 +166,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineCacheKey& key,
 | 
			
		||||
            info.fixed_state_point_size = point_size;
 | 
			
		||||
        }
 | 
			
		||||
        if (key.state.xfb_enabled != 0) {
 | 
			
		||||
            info.xfb_varyings = MakeTransformFeedbackVaryings(key);
 | 
			
		||||
            info.xfb_varyings = VideoCommon::MakeTransformFeedbackVaryings(key.state.xfb_state);
 | 
			
		||||
        }
 | 
			
		||||
        info.convert_depth_mode = gl_ndc;
 | 
			
		||||
        break;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										98
									
								
								src/video_core/transform_feedback.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/video_core/transform_feedback.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
			
		||||
// Copyright 2021 yuzu Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include "common/alignment.h"
 | 
			
		||||
#include "common/assert.h"
 | 
			
		||||
#include "shader_recompiler/shader_info.h"
 | 
			
		||||
#include "video_core/transform_feedback.h"
 | 
			
		||||
 | 
			
		||||
namespace VideoCommon {
 | 
			
		||||
 | 
			
		||||
std::vector<Shader::TransformFeedbackVarying> MakeTransformFeedbackVaryings(
 | 
			
		||||
    const TransformFeedbackState& state) {
 | 
			
		||||
    static constexpr std::array VECTORS{
 | 
			
		||||
        28,  // gl_Position
 | 
			
		||||
        32,  // Generic 0
 | 
			
		||||
        36,  // Generic 1
 | 
			
		||||
        40,  // Generic 2
 | 
			
		||||
        44,  // Generic 3
 | 
			
		||||
        48,  // Generic 4
 | 
			
		||||
        52,  // Generic 5
 | 
			
		||||
        56,  // Generic 6
 | 
			
		||||
        60,  // Generic 7
 | 
			
		||||
        64,  // Generic 8
 | 
			
		||||
        68,  // Generic 9
 | 
			
		||||
        72,  // Generic 10
 | 
			
		||||
        76,  // Generic 11
 | 
			
		||||
        80,  // Generic 12
 | 
			
		||||
        84,  // Generic 13
 | 
			
		||||
        88,  // Generic 14
 | 
			
		||||
        92,  // Generic 15
 | 
			
		||||
        96,  // Generic 16
 | 
			
		||||
        100, // Generic 17
 | 
			
		||||
        104, // Generic 18
 | 
			
		||||
        108, // Generic 19
 | 
			
		||||
        112, // Generic 20
 | 
			
		||||
        116, // Generic 21
 | 
			
		||||
        120, // Generic 22
 | 
			
		||||
        124, // Generic 23
 | 
			
		||||
        128, // Generic 24
 | 
			
		||||
        132, // Generic 25
 | 
			
		||||
        136, // Generic 26
 | 
			
		||||
        140, // Generic 27
 | 
			
		||||
        144, // Generic 28
 | 
			
		||||
        148, // Generic 29
 | 
			
		||||
        152, // Generic 30
 | 
			
		||||
        156, // Generic 31
 | 
			
		||||
        160, // gl_FrontColor
 | 
			
		||||
        164, // gl_FrontSecondaryColor
 | 
			
		||||
        160, // gl_BackColor
 | 
			
		||||
        164, // gl_BackSecondaryColor
 | 
			
		||||
        192, // gl_TexCoord[0]
 | 
			
		||||
        196, // gl_TexCoord[1]
 | 
			
		||||
        200, // gl_TexCoord[2]
 | 
			
		||||
        204, // gl_TexCoord[3]
 | 
			
		||||
        208, // gl_TexCoord[4]
 | 
			
		||||
        212, // gl_TexCoord[5]
 | 
			
		||||
        216, // gl_TexCoord[6]
 | 
			
		||||
        220, // gl_TexCoord[7]
 | 
			
		||||
    };
 | 
			
		||||
    std::vector<Shader::TransformFeedbackVarying> xfb(256);
 | 
			
		||||
    for (size_t buffer = 0; buffer < state.layouts.size(); ++buffer) {
 | 
			
		||||
        const auto& locations = state.varyings[buffer];
 | 
			
		||||
        const auto& layout = state.layouts[buffer];
 | 
			
		||||
        const u32 varying_count = layout.varying_count;
 | 
			
		||||
        u32 highest = 0;
 | 
			
		||||
        for (u32 offset = 0; offset < varying_count; ++offset) {
 | 
			
		||||
            const u32 base_offset = offset;
 | 
			
		||||
            const u8 location = locations[offset];
 | 
			
		||||
 | 
			
		||||
            Shader::TransformFeedbackVarying varying{
 | 
			
		||||
                .buffer = layout.stream,
 | 
			
		||||
                .stride = layout.stride,
 | 
			
		||||
                .offset = offset * 4,
 | 
			
		||||
                .components = 1,
 | 
			
		||||
            };
 | 
			
		||||
            if (std::ranges::find(VECTORS, Common::AlignDown(location, 4)) != VECTORS.end()) {
 | 
			
		||||
                UNIMPLEMENTED_IF_MSG(location % 4 != 0, "Unaligned TFB");
 | 
			
		||||
 | 
			
		||||
                const u8 base_index = location / 4;
 | 
			
		||||
                while (offset + 1 < varying_count && base_index == locations[offset + 1] / 4) {
 | 
			
		||||
                    ++offset;
 | 
			
		||||
                    ++varying.components;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            xfb[location] = varying;
 | 
			
		||||
            highest = std::max(highest, (base_offset + varying.components) * 4);
 | 
			
		||||
        }
 | 
			
		||||
        UNIMPLEMENTED_IF(highest != layout.stride);
 | 
			
		||||
    }
 | 
			
		||||
    return xfb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace VideoCommon
 | 
			
		||||
							
								
								
									
										30
									
								
								src/video_core/transform_feedback.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/video_core/transform_feedback.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
// Copyright 2021 yuzu Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "shader_recompiler/profile.h"
 | 
			
		||||
#include "video_core/engines/maxwell_3d.h"
 | 
			
		||||
 | 
			
		||||
namespace VideoCommon {
 | 
			
		||||
 | 
			
		||||
struct TransformFeedbackState {
 | 
			
		||||
    struct Layout {
 | 
			
		||||
        u32 stream;
 | 
			
		||||
        u32 varying_count;
 | 
			
		||||
        u32 stride;
 | 
			
		||||
    };
 | 
			
		||||
    std::array<Layout, Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers> layouts;
 | 
			
		||||
    std::array<std::array<u8, 128>, Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers>
 | 
			
		||||
        varyings;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::vector<Shader::TransformFeedbackVarying> MakeTransformFeedbackVaryings(
 | 
			
		||||
    const TransformFeedbackState& state);
 | 
			
		||||
 | 
			
		||||
} // namespace VideoCommon
 | 
			
		||||
		Reference in New Issue
	
	Block a user