Browse Source
Merge pull request #3244 from ReinUsesLisp/vk-fps
Merge pull request #3244 from ReinUsesLisp/vk-fps
fixed_pipeline_state: Define structure and loaderspull/15/merge
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 594 additions and 6 deletions
-
2src/video_core/CMakeLists.txt
-
20src/video_core/engines/maxwell_3d.h
-
296src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
-
282src/video_core/renderer_vulkan/fixed_pipeline_state.h
@ -0,0 +1,296 @@ |
|||||
|
// Copyright 2019 yuzu Emulator Project
|
||||
|
// Licensed under GPLv2 or any later version
|
||||
|
// Refer to the license.txt file included.
|
||||
|
|
||||
|
#include <tuple>
|
||||
|
|
||||
|
#include <boost/functional/hash.hpp>
|
||||
|
|
||||
|
#include "common/common_types.h"
|
||||
|
#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
|
||||
|
|
||||
|
namespace Vulkan { |
||||
|
|
||||
|
namespace { |
||||
|
|
||||
|
constexpr FixedPipelineState::DepthStencil GetDepthStencilState(const Maxwell& regs) { |
||||
|
const FixedPipelineState::StencilFace front_stencil( |
||||
|
regs.stencil_front_op_fail, regs.stencil_front_op_zfail, regs.stencil_front_op_zpass, |
||||
|
regs.stencil_front_func_func); |
||||
|
const FixedPipelineState::StencilFace back_stencil = |
||||
|
regs.stencil_two_side_enable |
||||
|
? FixedPipelineState::StencilFace(regs.stencil_back_op_fail, regs.stencil_back_op_zfail, |
||||
|
regs.stencil_back_op_zpass, |
||||
|
regs.stencil_back_func_func) |
||||
|
: front_stencil; |
||||
|
return FixedPipelineState::DepthStencil( |
||||
|
regs.depth_test_enable == 1, regs.depth_write_enabled == 1, regs.depth_bounds_enable == 1, |
||||
|
regs.stencil_enable == 1, regs.depth_test_func, front_stencil, back_stencil); |
||||
|
} |
||||
|
|
||||
|
constexpr FixedPipelineState::InputAssembly GetInputAssemblyState(const Maxwell& regs) { |
||||
|
return FixedPipelineState::InputAssembly( |
||||
|
regs.draw.topology, regs.primitive_restart.enabled, |
||||
|
regs.draw.topology == Maxwell::PrimitiveTopology::Points ? regs.point_size : 0.0f); |
||||
|
} |
||||
|
|
||||
|
constexpr FixedPipelineState::BlendingAttachment GetBlendingAttachmentState( |
||||
|
const Maxwell& regs, std::size_t render_target) { |
||||
|
const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : render_target]; |
||||
|
const std::array components = {mask.R != 0, mask.G != 0, mask.B != 0, mask.A != 0}; |
||||
|
|
||||
|
const FixedPipelineState::BlendingAttachment default_blending( |
||||
|
false, Maxwell::Blend::Equation::Add, Maxwell::Blend::Factor::One, |
||||
|
Maxwell::Blend::Factor::Zero, Maxwell::Blend::Equation::Add, Maxwell::Blend::Factor::One, |
||||
|
Maxwell::Blend::Factor::Zero, components); |
||||
|
if (render_target >= regs.rt_control.count) { |
||||
|
return default_blending; |
||||
|
} |
||||
|
|
||||
|
if (!regs.independent_blend_enable) { |
||||
|
const auto& src = regs.blend; |
||||
|
if (!src.enable[render_target]) { |
||||
|
return default_blending; |
||||
|
} |
||||
|
return FixedPipelineState::BlendingAttachment( |
||||
|
true, src.equation_rgb, src.factor_source_rgb, src.factor_dest_rgb, src.equation_a, |
||||
|
src.factor_source_a, src.factor_dest_a, components); |
||||
|
} |
||||
|
|
||||
|
if (!regs.blend.enable[render_target]) { |
||||
|
return default_blending; |
||||
|
} |
||||
|
const auto& src = regs.independent_blend[render_target]; |
||||
|
return FixedPipelineState::BlendingAttachment( |
||||
|
true, src.equation_rgb, src.factor_source_rgb, src.factor_dest_rgb, src.equation_a, |
||||
|
src.factor_source_a, src.factor_dest_a, components); |
||||
|
} |
||||
|
|
||||
|
constexpr FixedPipelineState::ColorBlending GetColorBlendingState(const Maxwell& regs) { |
||||
|
return FixedPipelineState::ColorBlending( |
||||
|
{regs.blend_color.r, regs.blend_color.g, regs.blend_color.b, regs.blend_color.a}, |
||||
|
regs.rt_control.count, |
||||
|
{GetBlendingAttachmentState(regs, 0), GetBlendingAttachmentState(regs, 1), |
||||
|
GetBlendingAttachmentState(regs, 2), GetBlendingAttachmentState(regs, 3), |
||||
|
GetBlendingAttachmentState(regs, 4), GetBlendingAttachmentState(regs, 5), |
||||
|
GetBlendingAttachmentState(regs, 6), GetBlendingAttachmentState(regs, 7)}); |
||||
|
} |
||||
|
|
||||
|
constexpr FixedPipelineState::Tessellation GetTessellationState(const Maxwell& regs) { |
||||
|
return FixedPipelineState::Tessellation(regs.patch_vertices, regs.tess_mode.prim, |
||||
|
regs.tess_mode.spacing, regs.tess_mode.cw != 0); |
||||
|
} |
||||
|
|
||||
|
constexpr std::size_t Point = 0; |
||||
|
constexpr std::size_t Line = 1; |
||||
|
constexpr std::size_t Polygon = 2; |
||||
|
constexpr std::array PolygonOffsetEnableLUT = { |
||||
|
Point, // Points
|
||||
|
Line, // Lines
|
||||
|
Line, // LineLoop
|
||||
|
Line, // LineStrip
|
||||
|
Polygon, // Triangles
|
||||
|
Polygon, // TriangleStrip
|
||||
|
Polygon, // TriangleFan
|
||||
|
Polygon, // Quads
|
||||
|
Polygon, // QuadStrip
|
||||
|
Polygon, // Polygon
|
||||
|
Line, // LinesAdjacency
|
||||
|
Line, // LineStripAdjacency
|
||||
|
Polygon, // TrianglesAdjacency
|
||||
|
Polygon, // TriangleStripAdjacency
|
||||
|
Polygon, // Patches
|
||||
|
}; |
||||
|
|
||||
|
constexpr FixedPipelineState::Rasterizer GetRasterizerState(const Maxwell& regs) { |
||||
|
const std::array enabled_lut = {regs.polygon_offset_point_enable, |
||||
|
regs.polygon_offset_line_enable, |
||||
|
regs.polygon_offset_fill_enable}; |
||||
|
const auto topology = static_cast<std::size_t>(regs.draw.topology.Value()); |
||||
|
const bool depth_bias_enabled = enabled_lut[PolygonOffsetEnableLUT[topology]]; |
||||
|
|
||||
|
Maxwell::Cull::FrontFace front_face = regs.cull.front_face; |
||||
|
if (regs.screen_y_control.triangle_rast_flip != 0 && |
||||
|
regs.viewport_transform[0].scale_y > 0.0f) { |
||||
|
if (front_face == Maxwell::Cull::FrontFace::CounterClockWise) |
||||
|
front_face = Maxwell::Cull::FrontFace::ClockWise; |
||||
|
else if (front_face == Maxwell::Cull::FrontFace::ClockWise) |
||||
|
front_face = Maxwell::Cull::FrontFace::CounterClockWise; |
||||
|
} |
||||
|
|
||||
|
const bool gl_ndc = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne; |
||||
|
return FixedPipelineState::Rasterizer(regs.cull.enabled, depth_bias_enabled, gl_ndc, |
||||
|
regs.cull.cull_face, front_face); |
||||
|
} |
||||
|
|
||||
|
} // Anonymous namespace
|
||||
|
|
||||
|
std::size_t FixedPipelineState::VertexBinding::Hash() const noexcept { |
||||
|
return (index << stride) ^ divisor; |
||||
|
} |
||||
|
|
||||
|
bool FixedPipelineState::VertexBinding::operator==(const VertexBinding& rhs) const noexcept { |
||||
|
return std::tie(index, stride, divisor) == std::tie(rhs.index, rhs.stride, rhs.divisor); |
||||
|
} |
||||
|
|
||||
|
std::size_t FixedPipelineState::VertexAttribute::Hash() const noexcept { |
||||
|
return static_cast<std::size_t>(index) ^ (static_cast<std::size_t>(buffer) << 13) ^ |
||||
|
(static_cast<std::size_t>(type) << 22) ^ (static_cast<std::size_t>(size) << 31) ^ |
||||
|
(static_cast<std::size_t>(offset) << 36); |
||||
|
} |
||||
|
|
||||
|
bool FixedPipelineState::VertexAttribute::operator==(const VertexAttribute& rhs) const noexcept { |
||||
|
return std::tie(index, buffer, type, size, offset) == |
||||
|
std::tie(rhs.index, rhs.buffer, rhs.type, rhs.size, rhs.offset); |
||||
|
} |
||||
|
|
||||
|
std::size_t FixedPipelineState::StencilFace::Hash() const noexcept { |
||||
|
return static_cast<std::size_t>(action_stencil_fail) ^ |
||||
|
(static_cast<std::size_t>(action_depth_fail) << 4) ^ |
||||
|
(static_cast<std::size_t>(action_depth_fail) << 20) ^ |
||||
|
(static_cast<std::size_t>(action_depth_pass) << 36); |
||||
|
} |
||||
|
|
||||
|
bool FixedPipelineState::StencilFace::operator==(const StencilFace& rhs) const noexcept { |
||||
|
return std::tie(action_stencil_fail, action_depth_fail, action_depth_pass, test_func) == |
||||
|
std::tie(rhs.action_stencil_fail, rhs.action_depth_fail, rhs.action_depth_pass, |
||||
|
rhs.test_func); |
||||
|
} |
||||
|
|
||||
|
std::size_t FixedPipelineState::BlendingAttachment::Hash() const noexcept { |
||||
|
return static_cast<std::size_t>(enable) ^ (static_cast<std::size_t>(rgb_equation) << 5) ^ |
||||
|
(static_cast<std::size_t>(src_rgb_func) << 10) ^ |
||||
|
(static_cast<std::size_t>(dst_rgb_func) << 15) ^ |
||||
|
(static_cast<std::size_t>(a_equation) << 20) ^ |
||||
|
(static_cast<std::size_t>(src_a_func) << 25) ^ |
||||
|
(static_cast<std::size_t>(dst_a_func) << 30) ^ |
||||
|
(static_cast<std::size_t>(components[0]) << 35) ^ |
||||
|
(static_cast<std::size_t>(components[1]) << 36) ^ |
||||
|
(static_cast<std::size_t>(components[2]) << 37) ^ |
||||
|
(static_cast<std::size_t>(components[3]) << 38); |
||||
|
} |
||||
|
|
||||
|
bool FixedPipelineState::BlendingAttachment::operator==(const BlendingAttachment& rhs) const |
||||
|
noexcept { |
||||
|
return std::tie(enable, rgb_equation, src_rgb_func, dst_rgb_func, a_equation, src_a_func, |
||||
|
dst_a_func, components) == |
||||
|
std::tie(rhs.enable, rhs.rgb_equation, rhs.src_rgb_func, rhs.dst_rgb_func, |
||||
|
rhs.a_equation, rhs.src_a_func, rhs.dst_a_func, rhs.components); |
||||
|
} |
||||
|
|
||||
|
std::size_t FixedPipelineState::VertexInput::Hash() const noexcept { |
||||
|
std::size_t hash = num_bindings ^ (num_attributes << 32); |
||||
|
for (std::size_t i = 0; i < num_bindings; ++i) { |
||||
|
boost::hash_combine(hash, bindings[i].Hash()); |
||||
|
} |
||||
|
for (std::size_t i = 0; i < num_attributes; ++i) { |
||||
|
boost::hash_combine(hash, attributes[i].Hash()); |
||||
|
} |
||||
|
return hash; |
||||
|
} |
||||
|
|
||||
|
bool FixedPipelineState::VertexInput::operator==(const VertexInput& rhs) const noexcept { |
||||
|
return std::equal(bindings.begin(), bindings.begin() + num_bindings, rhs.bindings.begin(), |
||||
|
rhs.bindings.begin() + rhs.num_bindings) && |
||||
|
std::equal(attributes.begin(), attributes.begin() + num_attributes, |
||||
|
rhs.attributes.begin(), rhs.attributes.begin() + rhs.num_attributes); |
||||
|
} |
||||
|
|
||||
|
std::size_t FixedPipelineState::InputAssembly::Hash() const noexcept { |
||||
|
std::size_t point_size_int = 0; |
||||
|
std::memcpy(&point_size_int, &point_size, sizeof(point_size)); |
||||
|
return (static_cast<std::size_t>(topology) << 24) ^ (point_size_int << 32) ^ |
||||
|
static_cast<std::size_t>(primitive_restart_enable); |
||||
|
} |
||||
|
|
||||
|
bool FixedPipelineState::InputAssembly::operator==(const InputAssembly& rhs) const noexcept { |
||||
|
return std::tie(topology, primitive_restart_enable, point_size) == |
||||
|
std::tie(rhs.topology, rhs.primitive_restart_enable, rhs.point_size); |
||||
|
} |
||||
|
|
||||
|
std::size_t FixedPipelineState::Tessellation::Hash() const noexcept { |
||||
|
return static_cast<std::size_t>(patch_control_points) ^ |
||||
|
(static_cast<std::size_t>(primitive) << 6) ^ (static_cast<std::size_t>(spacing) << 8) ^ |
||||
|
(static_cast<std::size_t>(clockwise) << 10); |
||||
|
} |
||||
|
|
||||
|
bool FixedPipelineState::Tessellation::operator==(const Tessellation& rhs) const noexcept { |
||||
|
return std::tie(patch_control_points, primitive, spacing, clockwise) == |
||||
|
std::tie(rhs.patch_control_points, rhs.primitive, rhs.spacing, rhs.clockwise); |
||||
|
} |
||||
|
|
||||
|
std::size_t FixedPipelineState::Rasterizer::Hash() const noexcept { |
||||
|
return static_cast<std::size_t>(cull_enable) ^ |
||||
|
(static_cast<std::size_t>(depth_bias_enable) << 1) ^ |
||||
|
(static_cast<std::size_t>(ndc_minus_one_to_one) << 2) ^ |
||||
|
(static_cast<std::size_t>(cull_face) << 24) ^ |
||||
|
(static_cast<std::size_t>(front_face) << 48); |
||||
|
} |
||||
|
|
||||
|
bool FixedPipelineState::Rasterizer::operator==(const Rasterizer& rhs) const noexcept { |
||||
|
return std::tie(cull_enable, depth_bias_enable, ndc_minus_one_to_one, cull_face, front_face) == |
||||
|
std::tie(rhs.cull_enable, rhs.depth_bias_enable, rhs.ndc_minus_one_to_one, rhs.cull_face, |
||||
|
rhs.front_face); |
||||
|
} |
||||
|
|
||||
|
std::size_t FixedPipelineState::DepthStencil::Hash() const noexcept { |
||||
|
std::size_t hash = static_cast<std::size_t>(depth_test_enable) ^ |
||||
|
(static_cast<std::size_t>(depth_write_enable) << 1) ^ |
||||
|
(static_cast<std::size_t>(depth_bounds_enable) << 2) ^ |
||||
|
(static_cast<std::size_t>(stencil_enable) << 3) ^ |
||||
|
(static_cast<std::size_t>(depth_test_function) << 4); |
||||
|
boost::hash_combine(hash, front_stencil.Hash()); |
||||
|
boost::hash_combine(hash, back_stencil.Hash()); |
||||
|
return hash; |
||||
|
} |
||||
|
|
||||
|
bool FixedPipelineState::DepthStencil::operator==(const DepthStencil& rhs) const noexcept { |
||||
|
return std::tie(depth_test_enable, depth_write_enable, depth_bounds_enable, depth_test_function, |
||||
|
stencil_enable, front_stencil, back_stencil) == |
||||
|
std::tie(rhs.depth_test_enable, rhs.depth_write_enable, rhs.depth_bounds_enable, |
||||
|
rhs.depth_test_function, rhs.stencil_enable, rhs.front_stencil, |
||||
|
rhs.back_stencil); |
||||
|
} |
||||
|
|
||||
|
std::size_t FixedPipelineState::ColorBlending::Hash() const noexcept { |
||||
|
std::size_t hash = attachments_count << 13; |
||||
|
for (std::size_t rt = 0; rt < static_cast<std::size_t>(attachments_count); ++rt) { |
||||
|
boost::hash_combine(hash, attachments[rt].Hash()); |
||||
|
} |
||||
|
return hash; |
||||
|
} |
||||
|
|
||||
|
bool FixedPipelineState::ColorBlending::operator==(const ColorBlending& rhs) const noexcept { |
||||
|
return std::equal(attachments.begin(), attachments.begin() + attachments_count, |
||||
|
rhs.attachments.begin(), rhs.attachments.begin() + rhs.attachments_count); |
||||
|
} |
||||
|
|
||||
|
std::size_t FixedPipelineState::Hash() const noexcept { |
||||
|
std::size_t hash = 0; |
||||
|
boost::hash_combine(hash, vertex_input.Hash()); |
||||
|
boost::hash_combine(hash, input_assembly.Hash()); |
||||
|
boost::hash_combine(hash, tessellation.Hash()); |
||||
|
boost::hash_combine(hash, rasterizer.Hash()); |
||||
|
boost::hash_combine(hash, depth_stencil.Hash()); |
||||
|
boost::hash_combine(hash, color_blending.Hash()); |
||||
|
return hash; |
||||
|
} |
||||
|
|
||||
|
bool FixedPipelineState::operator==(const FixedPipelineState& rhs) const noexcept { |
||||
|
return std::tie(vertex_input, input_assembly, tessellation, rasterizer, depth_stencil, |
||||
|
color_blending) == std::tie(rhs.vertex_input, rhs.input_assembly, |
||||
|
rhs.tessellation, rhs.rasterizer, rhs.depth_stencil, |
||||
|
rhs.color_blending); |
||||
|
} |
||||
|
|
||||
|
FixedPipelineState GetFixedPipelineState(const Maxwell& regs) { |
||||
|
FixedPipelineState fixed_state; |
||||
|
fixed_state.input_assembly = GetInputAssemblyState(regs); |
||||
|
fixed_state.tessellation = GetTessellationState(regs); |
||||
|
fixed_state.rasterizer = GetRasterizerState(regs); |
||||
|
fixed_state.depth_stencil = GetDepthStencilState(regs); |
||||
|
fixed_state.color_blending = GetColorBlendingState(regs); |
||||
|
return fixed_state; |
||||
|
} |
||||
|
|
||||
|
} // namespace Vulkan
|
||||
@ -0,0 +1,282 @@ |
|||||
|
// Copyright 2019 yuzu Emulator Project |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <array> |
||||
|
#include <type_traits> |
||||
|
|
||||
|
#include "common/common_types.h" |
||||
|
|
||||
|
#include "video_core/engines/maxwell_3d.h" |
||||
|
#include "video_core/surface.h" |
||||
|
|
||||
|
namespace Vulkan { |
||||
|
|
||||
|
using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
||||
|
|
||||
|
// TODO(Rodrigo): Optimize this structure. |
||||
|
|
||||
|
struct FixedPipelineState { |
||||
|
using PixelFormat = VideoCore::Surface::PixelFormat; |
||||
|
|
||||
|
struct VertexBinding { |
||||
|
constexpr VertexBinding(u32 index, u32 stride, u32 divisor) |
||||
|
: index{index}, stride{stride}, divisor{divisor} {} |
||||
|
VertexBinding() = default; |
||||
|
|
||||
|
u32 index; |
||||
|
u32 stride; |
||||
|
u32 divisor; |
||||
|
|
||||
|
std::size_t Hash() const noexcept; |
||||
|
|
||||
|
bool operator==(const VertexBinding& rhs) const noexcept; |
||||
|
|
||||
|
bool operator!=(const VertexBinding& rhs) const noexcept { |
||||
|
return !operator==(rhs); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct VertexAttribute { |
||||
|
constexpr VertexAttribute(u32 index, u32 buffer, Maxwell::VertexAttribute::Type type, |
||||
|
Maxwell::VertexAttribute::Size size, u32 offset) |
||||
|
: index{index}, buffer{buffer}, type{type}, size{size}, offset{offset} {} |
||||
|
VertexAttribute() = default; |
||||
|
|
||||
|
u32 index; |
||||
|
u32 buffer; |
||||
|
Maxwell::VertexAttribute::Type type; |
||||
|
Maxwell::VertexAttribute::Size size; |
||||
|
u32 offset; |
||||
|
|
||||
|
std::size_t Hash() const noexcept; |
||||
|
|
||||
|
bool operator==(const VertexAttribute& rhs) const noexcept; |
||||
|
|
||||
|
bool operator!=(const VertexAttribute& rhs) const noexcept { |
||||
|
return !operator==(rhs); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct StencilFace { |
||||
|
constexpr StencilFace(Maxwell::StencilOp action_stencil_fail, |
||||
|
Maxwell::StencilOp action_depth_fail, |
||||
|
Maxwell::StencilOp action_depth_pass, Maxwell::ComparisonOp test_func) |
||||
|
: action_stencil_fail{action_stencil_fail}, action_depth_fail{action_depth_fail}, |
||||
|
action_depth_pass{action_depth_pass}, test_func{test_func} {} |
||||
|
StencilFace() = default; |
||||
|
|
||||
|
Maxwell::StencilOp action_stencil_fail; |
||||
|
Maxwell::StencilOp action_depth_fail; |
||||
|
Maxwell::StencilOp action_depth_pass; |
||||
|
Maxwell::ComparisonOp test_func; |
||||
|
|
||||
|
std::size_t Hash() const noexcept; |
||||
|
|
||||
|
bool operator==(const StencilFace& rhs) const noexcept; |
||||
|
|
||||
|
bool operator!=(const StencilFace& rhs) const noexcept { |
||||
|
return !operator==(rhs); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct BlendingAttachment { |
||||
|
constexpr BlendingAttachment(bool enable, Maxwell::Blend::Equation rgb_equation, |
||||
|
Maxwell::Blend::Factor src_rgb_func, |
||||
|
Maxwell::Blend::Factor dst_rgb_func, |
||||
|
Maxwell::Blend::Equation a_equation, |
||||
|
Maxwell::Blend::Factor src_a_func, |
||||
|
Maxwell::Blend::Factor dst_a_func, |
||||
|
std::array<bool, 4> components) |
||||
|
: enable{enable}, rgb_equation{rgb_equation}, src_rgb_func{src_rgb_func}, |
||||
|
dst_rgb_func{dst_rgb_func}, a_equation{a_equation}, src_a_func{src_a_func}, |
||||
|
dst_a_func{dst_a_func}, components{components} {} |
||||
|
BlendingAttachment() = default; |
||||
|
|
||||
|
bool enable; |
||||
|
Maxwell::Blend::Equation rgb_equation; |
||||
|
Maxwell::Blend::Factor src_rgb_func; |
||||
|
Maxwell::Blend::Factor dst_rgb_func; |
||||
|
Maxwell::Blend::Equation a_equation; |
||||
|
Maxwell::Blend::Factor src_a_func; |
||||
|
Maxwell::Blend::Factor dst_a_func; |
||||
|
std::array<bool, 4> components; |
||||
|
|
||||
|
std::size_t Hash() const noexcept; |
||||
|
|
||||
|
bool operator==(const BlendingAttachment& rhs) const noexcept; |
||||
|
|
||||
|
bool operator!=(const BlendingAttachment& rhs) const noexcept { |
||||
|
return !operator==(rhs); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct VertexInput { |
||||
|
std::size_t num_bindings = 0; |
||||
|
std::size_t num_attributes = 0; |
||||
|
std::array<VertexBinding, Maxwell::NumVertexArrays> bindings; |
||||
|
std::array<VertexAttribute, Maxwell::NumVertexAttributes> attributes; |
||||
|
|
||||
|
std::size_t Hash() const noexcept; |
||||
|
|
||||
|
bool operator==(const VertexInput& rhs) const noexcept; |
||||
|
|
||||
|
bool operator!=(const VertexInput& rhs) const noexcept { |
||||
|
return !operator==(rhs); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct InputAssembly { |
||||
|
constexpr InputAssembly(Maxwell::PrimitiveTopology topology, bool primitive_restart_enable, |
||||
|
float point_size) |
||||
|
: topology{topology}, primitive_restart_enable{primitive_restart_enable}, |
||||
|
point_size{point_size} {} |
||||
|
InputAssembly() = default; |
||||
|
|
||||
|
Maxwell::PrimitiveTopology topology; |
||||
|
bool primitive_restart_enable; |
||||
|
float point_size; |
||||
|
|
||||
|
std::size_t Hash() const noexcept; |
||||
|
|
||||
|
bool operator==(const InputAssembly& rhs) const noexcept; |
||||
|
|
||||
|
bool operator!=(const InputAssembly& rhs) const noexcept { |
||||
|
return !operator==(rhs); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct Tessellation { |
||||
|
constexpr Tessellation(u32 patch_control_points, Maxwell::TessellationPrimitive primitive, |
||||
|
Maxwell::TessellationSpacing spacing, bool clockwise) |
||||
|
: patch_control_points{patch_control_points}, primitive{primitive}, spacing{spacing}, |
||||
|
clockwise{clockwise} {} |
||||
|
Tessellation() = default; |
||||
|
|
||||
|
u32 patch_control_points; |
||||
|
Maxwell::TessellationPrimitive primitive; |
||||
|
Maxwell::TessellationSpacing spacing; |
||||
|
bool clockwise; |
||||
|
|
||||
|
std::size_t Hash() const noexcept; |
||||
|
|
||||
|
bool operator==(const Tessellation& rhs) const noexcept; |
||||
|
|
||||
|
bool operator!=(const Tessellation& rhs) const noexcept { |
||||
|
return !operator==(rhs); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct Rasterizer { |
||||
|
constexpr Rasterizer(bool cull_enable, bool depth_bias_enable, bool ndc_minus_one_to_one, |
||||
|
Maxwell::Cull::CullFace cull_face, Maxwell::Cull::FrontFace front_face) |
||||
|
: cull_enable{cull_enable}, depth_bias_enable{depth_bias_enable}, |
||||
|
ndc_minus_one_to_one{ndc_minus_one_to_one}, cull_face{cull_face}, front_face{ |
||||
|
front_face} {} |
||||
|
Rasterizer() = default; |
||||
|
|
||||
|
bool cull_enable; |
||||
|
bool depth_bias_enable; |
||||
|
bool ndc_minus_one_to_one; |
||||
|
Maxwell::Cull::CullFace cull_face; |
||||
|
Maxwell::Cull::FrontFace front_face; |
||||
|
|
||||
|
std::size_t Hash() const noexcept; |
||||
|
|
||||
|
bool operator==(const Rasterizer& rhs) const noexcept; |
||||
|
|
||||
|
bool operator!=(const Rasterizer& rhs) const noexcept { |
||||
|
return !operator==(rhs); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct DepthStencil { |
||||
|
constexpr DepthStencil(bool depth_test_enable, bool depth_write_enable, |
||||
|
bool depth_bounds_enable, bool stencil_enable, |
||||
|
Maxwell::ComparisonOp depth_test_function, StencilFace front_stencil, |
||||
|
StencilFace back_stencil) |
||||
|
: depth_test_enable{depth_test_enable}, depth_write_enable{depth_write_enable}, |
||||
|
depth_bounds_enable{depth_bounds_enable}, stencil_enable{stencil_enable}, |
||||
|
depth_test_function{depth_test_function}, front_stencil{front_stencil}, |
||||
|
back_stencil{back_stencil} {} |
||||
|
DepthStencil() = default; |
||||
|
|
||||
|
bool depth_test_enable; |
||||
|
bool depth_write_enable; |
||||
|
bool depth_bounds_enable; |
||||
|
bool stencil_enable; |
||||
|
Maxwell::ComparisonOp depth_test_function; |
||||
|
StencilFace front_stencil; |
||||
|
StencilFace back_stencil; |
||||
|
|
||||
|
std::size_t Hash() const noexcept; |
||||
|
|
||||
|
bool operator==(const DepthStencil& rhs) const noexcept; |
||||
|
|
||||
|
bool operator!=(const DepthStencil& rhs) const noexcept { |
||||
|
return !operator==(rhs); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct ColorBlending { |
||||
|
constexpr ColorBlending( |
||||
|
std::array<float, 4> blend_constants, std::size_t attachments_count, |
||||
|
std::array<BlendingAttachment, Maxwell::NumRenderTargets> attachments) |
||||
|
: attachments_count{attachments_count}, attachments{attachments} {} |
||||
|
ColorBlending() = default; |
||||
|
|
||||
|
std::size_t attachments_count; |
||||
|
std::array<BlendingAttachment, Maxwell::NumRenderTargets> attachments; |
||||
|
|
||||
|
std::size_t Hash() const noexcept; |
||||
|
|
||||
|
bool operator==(const ColorBlending& rhs) const noexcept; |
||||
|
|
||||
|
bool operator!=(const ColorBlending& rhs) const noexcept { |
||||
|
return !operator==(rhs); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
std::size_t Hash() const noexcept; |
||||
|
|
||||
|
bool operator==(const FixedPipelineState& rhs) const noexcept; |
||||
|
|
||||
|
bool operator!=(const FixedPipelineState& rhs) const noexcept { |
||||
|
return !operator==(rhs); |
||||
|
} |
||||
|
|
||||
|
VertexInput vertex_input; |
||||
|
InputAssembly input_assembly; |
||||
|
Tessellation tessellation; |
||||
|
Rasterizer rasterizer; |
||||
|
DepthStencil depth_stencil; |
||||
|
ColorBlending color_blending; |
||||
|
}; |
||||
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexBinding>); |
||||
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexAttribute>); |
||||
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState::StencilFace>); |
||||
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState::BlendingAttachment>); |
||||
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexInput>); |
||||
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState::InputAssembly>); |
||||
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState::Tessellation>); |
||||
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState::Rasterizer>); |
||||
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState::DepthStencil>); |
||||
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState::ColorBlending>); |
||||
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState>); |
||||
|
|
||||
|
FixedPipelineState GetFixedPipelineState(const Maxwell& regs); |
||||
|
|
||||
|
} // namespace Vulkan |
||||
|
|
||||
|
namespace std { |
||||
|
|
||||
|
template <> |
||||
|
struct hash<Vulkan::FixedPipelineState> { |
||||
|
std::size_t operator()(const Vulkan::FixedPipelineState& k) const noexcept { |
||||
|
return k.Hash(); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
} // namespace std |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue