Skip to content

Commit

Permalink
Change BitfieldExtract to use a pointer to the bitfield member
Browse files Browse the repository at this point in the history
  • Loading branch information
Pokechu22 committed May 7, 2021
1 parent e7f68cf commit 0f7c9ef
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 79 deletions.
4 changes: 2 additions & 2 deletions Source/Core/Common/BitField.h
Expand Up @@ -155,8 +155,8 @@ struct BitField

constexpr T Value() const { return Value(std::is_signed<T>()); }
constexpr operator T() const { return Value(); }
constexpr std::size_t StartBit() const { return position; }
constexpr std::size_t NumBits() const { return bits; }
static constexpr std::size_t StartBit() { return position; }
static constexpr std::size_t NumBits() { return bits; }

private:
// Unsigned version of StorageType
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Common/CMakeLists.txt
Expand Up @@ -125,6 +125,7 @@ add_library(common
TraversalClient.cpp
TraversalClient.h
TraversalProto.h
TypeUtils.h
UPnP.cpp
UPnP.h
VariantUtil.h
Expand Down
70 changes: 70 additions & 0 deletions Source/Core/Common/TypeUtils.h
@@ -0,0 +1,70 @@
// Copyright 2021 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#pragma once

#include <type_traits>

namespace Common
{
template <typename>
struct MemberPointerInfo;
// Helper to get information about a pointer to a data member.
// See https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_members
// This template takes the type for a member pointer.
template <typename M, typename O>
struct MemberPointerInfo<M O::*>
{
using MemberType = M;
using ObjectType = O;
};

// This template takes a specific member pointer.
template <auto member_pointer>
using MemberType = typename MemberPointerInfo<decltype(member_pointer)>::MemberType;

// This template takes a specific member pointer.
template <auto member_pointer>
using ObjectType = typename MemberPointerInfo<decltype(member_pointer)>::ObjectType;

namespace detail
{
template <int x>
struct Data
{
static constexpr int GetX() { return x; }
};
struct Foo
{
Data<1> a;
Data<2> b;
int c;
};
struct Bar : Foo
{
int d;
};

static_assert(std::is_same_v<MemberType<&Foo::a>, Data<1>>);
static_assert(MemberType<&Foo::a>::GetX() == 1);
static_assert(std::is_same_v<MemberType<&Foo::b>, Data<2>>);
static_assert(MemberType<&Foo::b>::GetX() == 2);
static_assert(std::is_same_v<MemberType<&Foo::c>, int>);

static_assert(std::is_same_v<ObjectType<&Foo::a>, Foo>);
static_assert(std::is_same_v<ObjectType<&Foo::b>, Foo>);
static_assert(std::is_same_v<ObjectType<&Foo::c>, Foo>);

static_assert(std::is_same_v<MemberType<&Foo::c>, MemberPointerInfo<int Foo::*>::MemberType>);
static_assert(std::is_same_v<ObjectType<&Foo::c>, MemberPointerInfo<int Foo::*>::ObjectType>);

static_assert(std::is_same_v<MemberType<&Bar::c>, int>);
static_assert(std::is_same_v<MemberType<&Bar::d>, int>);

static_assert(std::is_same_v<ObjectType<&Bar::d>, Bar>);
// Somewhat unexpected behavior:
static_assert(std::is_same_v<ObjectType<&Bar::c>, Foo>);
static_assert(!std::is_same_v<ObjectType<&Bar::c>, Bar>);
} // namespace detail
} // namespace Common
1 change: 1 addition & 0 deletions Source/Core/DolphinLib.props
Expand Up @@ -152,6 +152,7 @@
<ClInclude Include="Common\Timer.h" />
<ClInclude Include="Common\TraversalClient.h" />
<ClInclude Include="Common\TraversalProto.h" />
<ClInclude Include="Common\TypeUtils.h" />
<ClInclude Include="Common\UPnP.h" />
<ClInclude Include="Common\VariantUtil.h" />
<ClInclude Include="Common\Version.h" />
Expand Down
28 changes: 14 additions & 14 deletions Source/Core/VideoCommon/UberShaderCommon.cpp
Expand Up @@ -103,29 +103,29 @@ void WriteVertexLighting(ShaderCode& out, APIType api_type, std::string_view wor
" int4 lacc = int4(255, 255, 255, 255);\n"
"\n");

out.Write(" if ({} != 0u)\n", BitfieldExtract("colorreg", LitChannel().matsource));
out.Write(" if ({} != 0u)\n", BitfieldExtract<&LitChannel::matsource>("colorreg"));
out.Write(" mat.xyz = int3(round(((chan == 0u) ? {}.xyz : {}.xyz) * 255.0));\n",
in_color_0_var, in_color_1_var);

out.Write(" if ({} != 0u)\n", BitfieldExtract("alphareg", LitChannel().matsource));
out.Write(" if ({} != 0u)\n", BitfieldExtract<&LitChannel::matsource>("alphareg"));
out.Write(" mat.w = int(round(((chan == 0u) ? {}.w : {}.w) * 255.0));\n", in_color_0_var,
in_color_1_var);
out.Write(" else\n"
" mat.w = " I_MATERIALS " [chan + 2u].w;\n"
"\n");

out.Write(" if ({} != 0u) {{\n", BitfieldExtract("colorreg", LitChannel().enablelighting));
out.Write(" if ({} != 0u)\n", BitfieldExtract("colorreg", LitChannel().ambsource));
out.Write(" if ({} != 0u) {{\n", BitfieldExtract<&LitChannel::enablelighting>("colorreg"));
out.Write(" if ({} != 0u)\n", BitfieldExtract<&LitChannel::ambsource>("colorreg"));
out.Write(" lacc.xyz = int3(round(((chan == 0u) ? {}.xyz : {}.xyz) * 255.0));\n",
in_color_0_var, in_color_1_var);
out.Write(" else\n"
" lacc.xyz = " I_MATERIALS " [chan].xyz;\n"
"\n");
out.Write(" uint light_mask = {} | ({} << 4u);\n",
BitfieldExtract("colorreg", LitChannel().lightMask0_3),
BitfieldExtract("colorreg", LitChannel().lightMask4_7));
out.Write(" uint attnfunc = {};\n", BitfieldExtract("colorreg", LitChannel().attnfunc));
out.Write(" uint diffusefunc = {};\n", BitfieldExtract("colorreg", LitChannel().diffusefunc));
BitfieldExtract<&LitChannel::lightMask0_3>("colorreg"),
BitfieldExtract<&LitChannel::lightMask4_7>("colorreg"));
out.Write(" uint attnfunc = {};\n", BitfieldExtract<&LitChannel::attnfunc>("colorreg"));
out.Write(" uint diffusefunc = {};\n", BitfieldExtract<&LitChannel::diffusefunc>("colorreg"));
out.Write(
" for (uint light_index = 0u; light_index < 8u; light_index++) {{\n"
" if ((light_mask & (1u << light_index)) != 0u)\n"
Expand All @@ -135,8 +135,8 @@ void WriteVertexLighting(ShaderCode& out, APIType api_type, std::string_view wor
" }}\n"
"\n");

out.Write(" if ({} != 0u) {{\n", BitfieldExtract("alphareg", LitChannel().enablelighting));
out.Write(" if ({} != 0u) {{\n", BitfieldExtract("alphareg", LitChannel().ambsource));
out.Write(" if ({} != 0u) {{\n", BitfieldExtract<&LitChannel::enablelighting>("alphareg"));
out.Write(" if ({} != 0u) {{\n", BitfieldExtract<&LitChannel::ambsource>("alphareg"));
out.Write(" if ((components & ({}u << chan)) != 0u) // VB_HAS_COL0\n", VB_HAS_COL0);
out.Write(" lacc.w = int(round(((chan == 0u) ? {}.w : {}.w) * 255.0));\n", in_color_0_var,
in_color_1_var);
Expand All @@ -149,10 +149,10 @@ void WriteVertexLighting(ShaderCode& out, APIType api_type, std::string_view wor
" }}\n"
"\n");
out.Write(" uint light_mask = {} | ({} << 4u);\n",
BitfieldExtract("alphareg", LitChannel().lightMask0_3),
BitfieldExtract("alphareg", LitChannel().lightMask4_7));
out.Write(" uint attnfunc = {};\n", BitfieldExtract("alphareg", LitChannel().attnfunc));
out.Write(" uint diffusefunc = {};\n", BitfieldExtract("alphareg", LitChannel().diffusefunc));
BitfieldExtract<&LitChannel::lightMask0_3>("alphareg"),
BitfieldExtract<&LitChannel::lightMask4_7>("alphareg"));
out.Write(" uint attnfunc = {};\n", BitfieldExtract<&LitChannel::attnfunc>("alphareg"));
out.Write(" uint diffusefunc = {};\n", BitfieldExtract<&LitChannel::diffusefunc>("alphareg"));
out.Write(" for (uint light_index = 0u; light_index < 8u; light_index++) {{\n\n"
" if ((light_mask & (1u << light_index)) != 0u)\n\n"
" lacc.w += CalculateLighting(light_index, attnfunc, diffusefunc, {}, {}).w;\n",
Expand Down
10 changes: 6 additions & 4 deletions Source/Core/VideoCommon/UberShaderCommon.h
Expand Up @@ -10,6 +10,7 @@
#include <fmt/format.h>

#include "Common/CommonTypes.h"
#include "Common/TypeUtils.h"

class ShaderCode;
enum class APIType;
Expand All @@ -29,10 +30,11 @@ void WriteVertexLighting(ShaderCode& out, APIType api_type, std::string_view wor
std::string_view out_color_1_var);

// bitfieldExtract generator for BitField types
template <typename T>
std::string BitfieldExtract(std::string_view source, T type)
template <auto ptr_to_bitfield_member>
std::string BitfieldExtract(std::string_view source)
{
return fmt::format("bitfieldExtract({}, {}, {})", source, static_cast<u32>(type.StartBit()),
static_cast<u32>(type.NumBits()));
using BitFieldT = Common::MemberType<ptr_to_bitfield_member>;
return fmt::format("bitfieldExtract({}, {}, {})", source, static_cast<u32>(BitFieldT::StartBit()),
static_cast<u32>(BitFieldT::NumBits()));
}
} // namespace UberShader

0 comments on commit 0f7c9ef

Please sign in to comment.