summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_vulkan/vk_shader_decompiler.h
blob: 415801b6c5c09fbe461d1a07046da761d386ccc7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#pragma once

#include <array>
#include <bitset>
#include <memory>
#include <set>
#include <type_traits>
#include <utility>
#include <vector>

#include "common/common_types.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/engines/shader_type.h"
#include "video_core/shader/shader_ir.h"

namespace Vulkan {
class VKDevice;
}

namespace Vulkan {

using Maxwell = Tegra::Engines::Maxwell3D::Regs;
using TexelBufferEntry = VideoCommon::Shader::Sampler;
using SamplerEntry = VideoCommon::Shader::Sampler;
using ImageEntry = VideoCommon::Shader::Image;

constexpr u32 DESCRIPTOR_SET = 0;

class ConstBufferEntry : public VideoCommon::Shader::ConstBuffer {
public:
    explicit constexpr ConstBufferEntry(const VideoCommon::Shader::ConstBuffer& entry, u32 index)
        : VideoCommon::Shader::ConstBuffer{entry}, index{index} {}

    constexpr u32 GetIndex() const {
        return index;
    }

private:
    u32 index{};
};

class GlobalBufferEntry {
public:
    constexpr explicit GlobalBufferEntry(u32 cbuf_index, u32 cbuf_offset, bool is_written)
        : cbuf_index{cbuf_index}, cbuf_offset{cbuf_offset}, is_written{is_written} {}

    constexpr u32 GetCbufIndex() const {
        return cbuf_index;
    }

    constexpr u32 GetCbufOffset() const {
        return cbuf_offset;
    }

    constexpr bool IsWritten() const {
        return is_written;
    }

private:
    u32 cbuf_index{};
    u32 cbuf_offset{};
    bool is_written{};
};

struct ShaderEntries {
    u32 NumBindings() const {
        return static_cast<u32>(const_buffers.size() + global_buffers.size() +
                                texel_buffers.size() + samplers.size() + images.size());
    }

    std::vector<ConstBufferEntry> const_buffers;
    std::vector<GlobalBufferEntry> global_buffers;
    std::vector<TexelBufferEntry> texel_buffers;
    std::vector<SamplerEntry> samplers;
    std::vector<ImageEntry> images;
    std::set<u32> attributes;
    std::array<bool, Maxwell::NumClipDistances> clip_distances{};
    std::size_t shader_length{};
    bool uses_warps{};
};

struct Specialization final {
    u32 base_binding{};

    // Compute specific
    std::array<u32, 3> workgroup_size{};
    u32 shared_memory_size{};

    // Graphics specific
    Maxwell::PrimitiveTopology primitive_topology{};
    std::optional<float> point_size{};
    std::array<Maxwell::VertexAttribute::Type, Maxwell::NumVertexAttributes> attribute_types{};

    // Tessellation specific
    struct {
        Maxwell::TessellationPrimitive primitive{};
        Maxwell::TessellationSpacing spacing{};
        bool clockwise{};
    } tessellation;

    // Fragment specific
    std::bitset<8> enabled_rendertargets;
};
// Old gcc versions don't consider this trivially copyable.
// static_assert(std::is_trivially_copyable_v<Specialization>);

struct SPIRVShader {
    std::vector<u32> code;
    ShaderEntries entries;
};

ShaderEntries GenerateShaderEntries(const VideoCommon::Shader::ShaderIR& ir);

std::vector<u32> Decompile(const VKDevice& device, const VideoCommon::Shader::ShaderIR& ir,
                           Tegra::Engines::ShaderType stage, const Specialization& specialization);

} // namespace Vulkan