early-access version 2547
This commit is contained in:
parent
b98acbedfe
commit
f1141cfd5d
13 changed files with 97 additions and 23 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 2545.
|
This is the source code for early-access 2547.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -315,7 +315,7 @@ public:
|
||||||
private:
|
private:
|
||||||
constexpr explicit Iterator(ImplIterator it) : m_impl(it) {}
|
constexpr explicit Iterator(ImplIterator it) : m_impl(it) {}
|
||||||
|
|
||||||
constexpr explicit Iterator(ImplIterator::pointer p) : m_impl(p) {}
|
constexpr explicit Iterator(typename ImplIterator::pointer p) : m_impl(p) {}
|
||||||
|
|
||||||
constexpr ImplIterator GetImplIterator() const {
|
constexpr ImplIterator GetImplIterator() const {
|
||||||
return m_impl;
|
return m_impl;
|
||||||
|
|
|
@ -148,8 +148,8 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
|
||||||
config.wall_clock_cntpct = uses_wall_clock;
|
config.wall_clock_cntpct = uses_wall_clock;
|
||||||
|
|
||||||
// Code cache size
|
// Code cache size
|
||||||
config.code_cache_size = 512_MiB;
|
config.code_cache_size = 128_MiB;
|
||||||
config.far_code_offset = 400_MiB;
|
config.far_code_offset = 100_MiB;
|
||||||
|
|
||||||
// Safe optimizations
|
// Safe optimizations
|
||||||
if (Settings::values.cpu_debug_mode) {
|
if (Settings::values.cpu_debug_mode) {
|
||||||
|
|
|
@ -208,8 +208,8 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
|
||||||
config.wall_clock_cntpct = uses_wall_clock;
|
config.wall_clock_cntpct = uses_wall_clock;
|
||||||
|
|
||||||
// Code cache size
|
// Code cache size
|
||||||
config.code_cache_size = 512_MiB;
|
config.code_cache_size = 128_MiB;
|
||||||
config.far_code_offset = 400_MiB;
|
config.far_code_offset = 100_MiB;
|
||||||
|
|
||||||
// Safe optimizations
|
// Safe optimizations
|
||||||
if (Settings::values.cpu_debug_mode) {
|
if (Settings::values.cpu_debug_mode) {
|
||||||
|
|
|
@ -19,17 +19,13 @@ class KPageBuffer final : public KSlabAllocated<KPageBuffer> {
|
||||||
public:
|
public:
|
||||||
KPageBuffer() = default;
|
KPageBuffer() = default;
|
||||||
|
|
||||||
PAddr GetPhysicalAddress(Core::System& system) const {
|
|
||||||
return system.DeviceMemory().GetPhysicalAddr(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
static KPageBuffer* FromPhysicalAddress(Core::System& system, PAddr phys_addr) {
|
static KPageBuffer* FromPhysicalAddress(Core::System& system, PAddr phys_addr) {
|
||||||
ASSERT(Common::IsAligned(phys_addr, PageSize));
|
ASSERT(Common::IsAligned(phys_addr, PageSize));
|
||||||
return reinterpret_cast<KPageBuffer*>(system.DeviceMemory().GetPointer(phys_addr));
|
return reinterpret_cast<KPageBuffer*>(system.DeviceMemory().GetPointer(phys_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
alignas(PageSize) std::array<u8, PageSize> m_buffer{};
|
[[maybe_unused]] alignas(PageSize) std::array<u8, PageSize> m_buffer{};
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(KPageBuffer) == PageSize);
|
static_assert(sizeof(KPageBuffer) == PageSize);
|
||||||
|
|
|
@ -22,7 +22,7 @@ constexpr u32 NUM_TEXTURE_AND_IMAGE_SCALING_WORDS =
|
||||||
struct RescalingLayout {
|
struct RescalingLayout {
|
||||||
alignas(16) std::array<u32, NUM_TEXTURE_SCALING_WORDS> rescaling_textures;
|
alignas(16) std::array<u32, NUM_TEXTURE_SCALING_WORDS> rescaling_textures;
|
||||||
alignas(16) std::array<u32, NUM_IMAGE_SCALING_WORDS> rescaling_images;
|
alignas(16) std::array<u32, NUM_IMAGE_SCALING_WORDS> rescaling_images;
|
||||||
alignas(16) u32 down_factor;
|
u32 down_factor;
|
||||||
};
|
};
|
||||||
constexpr u32 RESCALING_LAYOUT_WORDS_OFFSET = offsetof(RescalingLayout, rescaling_textures);
|
constexpr u32 RESCALING_LAYOUT_WORDS_OFFSET = offsetof(RescalingLayout, rescaling_textures);
|
||||||
constexpr u32 RESCALING_LAYOUT_DOWN_FACTOR_OFFSET = offsetof(RescalingLayout, down_factor);
|
constexpr u32 RESCALING_LAYOUT_DOWN_FACTOR_OFFSET = offsetof(RescalingLayout, down_factor);
|
||||||
|
|
|
@ -212,11 +212,11 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
|
||||||
}
|
}
|
||||||
Optimization::SsaRewritePass(program);
|
Optimization::SsaRewritePass(program);
|
||||||
|
|
||||||
|
Optimization::ConstantPropagationPass(program);
|
||||||
|
|
||||||
Optimization::GlobalMemoryToStorageBufferPass(program);
|
Optimization::GlobalMemoryToStorageBufferPass(program);
|
||||||
Optimization::TexturePass(env, program);
|
Optimization::TexturePass(env, program);
|
||||||
|
|
||||||
Optimization::ConstantPropagationPass(program);
|
|
||||||
|
|
||||||
if (Settings::values.resolution_info.active) {
|
if (Settings::values.resolution_info.active) {
|
||||||
Optimization::RescalingPass(program);
|
Optimization::RescalingPass(program);
|
||||||
}
|
}
|
||||||
|
|
|
@ -334,7 +334,8 @@ std::optional<LowAddrInfo> TrackLowAddress(IR::Inst* inst) {
|
||||||
/// Tries to track the storage buffer address used by a global memory instruction
|
/// Tries to track the storage buffer address used by a global memory instruction
|
||||||
std::optional<StorageBufferAddr> Track(const IR::Value& value, const Bias* bias) {
|
std::optional<StorageBufferAddr> Track(const IR::Value& value, const Bias* bias) {
|
||||||
const auto pred{[bias](const IR::Inst* inst) -> std::optional<StorageBufferAddr> {
|
const auto pred{[bias](const IR::Inst* inst) -> std::optional<StorageBufferAddr> {
|
||||||
if (inst->GetOpcode() != IR::Opcode::GetCbufU32) {
|
if (inst->GetOpcode() != IR::Opcode::GetCbufU32 &&
|
||||||
|
inst->GetOpcode() != IR::Opcode::GetCbufU32x2) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
const IR::Value index{inst->Arg(0)};
|
const IR::Value index{inst->Arg(0)};
|
||||||
|
|
|
@ -183,6 +183,31 @@ void ScaleIntegerComposite(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScaleIntegerOffsetComposite(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_scaled,
|
||||||
|
size_t index) {
|
||||||
|
const IR::Value composite{inst.Arg(index)};
|
||||||
|
if (composite.IsEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto info{inst.Flags<IR::TextureInstInfo>()};
|
||||||
|
const IR::U32 x{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(composite, 0)})};
|
||||||
|
const IR::U32 y{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(composite, 1)})};
|
||||||
|
switch (info.type) {
|
||||||
|
case TextureType::ColorArray2D:
|
||||||
|
case TextureType::Color2D:
|
||||||
|
inst.SetArg(index, ir.CompositeConstruct(x, y));
|
||||||
|
break;
|
||||||
|
case TextureType::Color1D:
|
||||||
|
case TextureType::ColorArray1D:
|
||||||
|
case TextureType::Color3D:
|
||||||
|
case TextureType::ColorCube:
|
||||||
|
case TextureType::ColorArrayCube:
|
||||||
|
case TextureType::Buffer:
|
||||||
|
// Nothing to patch here
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SubScaleCoord(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_scaled) {
|
void SubScaleCoord(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_scaled) {
|
||||||
const auto info{inst.Flags<IR::TextureInstInfo>()};
|
const auto info{inst.Flags<IR::TextureInstInfo>()};
|
||||||
const IR::Value coord{inst.Arg(1)};
|
const IR::Value coord{inst.Arg(1)};
|
||||||
|
@ -220,7 +245,7 @@ void SubScaleImageFetch(IR::Block& block, IR::Inst& inst) {
|
||||||
const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))};
|
const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))};
|
||||||
SubScaleCoord(ir, inst, is_scaled);
|
SubScaleCoord(ir, inst, is_scaled);
|
||||||
// Scale ImageFetch offset
|
// Scale ImageFetch offset
|
||||||
ScaleIntegerComposite(ir, inst, is_scaled, 2);
|
ScaleIntegerOffsetComposite(ir, inst, is_scaled, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubScaleImageRead(IR::Block& block, IR::Inst& inst) {
|
void SubScaleImageRead(IR::Block& block, IR::Inst& inst) {
|
||||||
|
@ -242,7 +267,7 @@ void PatchImageFetch(IR::Block& block, IR::Inst& inst) {
|
||||||
const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))};
|
const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))};
|
||||||
ScaleIntegerComposite(ir, inst, is_scaled, 1);
|
ScaleIntegerComposite(ir, inst, is_scaled, 1);
|
||||||
// Scale ImageFetch offset
|
// Scale ImageFetch offset
|
||||||
ScaleIntegerComposite(ir, inst, is_scaled, 2);
|
ScaleIntegerOffsetComposite(ir, inst, is_scaled, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PatchImageRead(IR::Block& block, IR::Inst& inst) {
|
void PatchImageRead(IR::Block& block, IR::Inst& inst) {
|
||||||
|
|
|
@ -370,8 +370,31 @@ void Maxwell3D::CallMethodFromMME(u32 method, u32 method_argument) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::ProcessTopologyOverride() {
|
void Maxwell3D::ProcessTopologyOverride() {
|
||||||
|
using PrimitiveTopology = Maxwell3D::Regs::PrimitiveTopology;
|
||||||
|
using PrimitiveTopologyOverride = Maxwell3D::Regs::PrimitiveTopologyOverride;
|
||||||
|
|
||||||
|
PrimitiveTopology topology{};
|
||||||
|
|
||||||
|
switch (regs.topology_override) {
|
||||||
|
case PrimitiveTopologyOverride::None:
|
||||||
|
topology = regs.draw.topology;
|
||||||
|
break;
|
||||||
|
case PrimitiveTopologyOverride::Points:
|
||||||
|
topology = PrimitiveTopology::Points;
|
||||||
|
break;
|
||||||
|
case PrimitiveTopologyOverride::Lines:
|
||||||
|
topology = PrimitiveTopology::Lines;
|
||||||
|
break;
|
||||||
|
case PrimitiveTopologyOverride::LineStrip:
|
||||||
|
topology = PrimitiveTopology::LineStrip;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
topology = static_cast<PrimitiveTopology>(regs.topology_override);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (use_topology_override) {
|
if (use_topology_override) {
|
||||||
regs.draw.topology.Assign(regs.topology_override);
|
regs.draw.topology.Assign(topology);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -367,6 +367,22 @@ public:
|
||||||
Patches = 0xe,
|
Patches = 0xe,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Constants as from NVC0_3D_UNK1970_D3D
|
||||||
|
// https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/gallium/drivers/nouveau/nvc0/nvc0_3d.xml.h#L1598
|
||||||
|
enum class PrimitiveTopologyOverride : u32 {
|
||||||
|
None = 0x0,
|
||||||
|
Points = 0x1,
|
||||||
|
Lines = 0x2,
|
||||||
|
LineStrip = 0x3,
|
||||||
|
Triangles = 0x4,
|
||||||
|
TriangleStrip = 0x5,
|
||||||
|
LinesAdjacency = 0xa,
|
||||||
|
LineStripAdjacency = 0xb,
|
||||||
|
TrianglesAdjacency = 0xc,
|
||||||
|
TriangleStripAdjacency = 0xd,
|
||||||
|
Patches = 0xe,
|
||||||
|
};
|
||||||
|
|
||||||
enum class IndexFormat : u32 {
|
enum class IndexFormat : u32 {
|
||||||
UnsignedByte = 0x0,
|
UnsignedByte = 0x0,
|
||||||
UnsignedShort = 0x1,
|
UnsignedShort = 0x1,
|
||||||
|
@ -1251,7 +1267,7 @@ public:
|
||||||
|
|
||||||
INSERT_PADDING_WORDS_NOINIT(0xC);
|
INSERT_PADDING_WORDS_NOINIT(0xC);
|
||||||
|
|
||||||
PrimitiveTopology topology_override;
|
PrimitiveTopologyOverride topology_override;
|
||||||
|
|
||||||
INSERT_PADDING_WORDS_NOINIT(0x12);
|
INSERT_PADDING_WORDS_NOINIT(0x12);
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
@ -292,7 +293,7 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble(
|
||||||
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_INDEX_READ_BIT,
|
.dstAccessMask = VK_ACCESS_INDEX_READ_BIT,
|
||||||
};
|
};
|
||||||
const std::array push_constants{base_vertex, index_shift};
|
const std::array<u32, 2> push_constants{base_vertex, index_shift};
|
||||||
const VkDescriptorSet set = descriptor_allocator.Commit();
|
const VkDescriptorSet set = descriptor_allocator.Commit();
|
||||||
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
|
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
|
||||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
|
||||||
|
|
|
@ -369,7 +369,7 @@ template <bool has_blacklists>
|
||||||
void TextureCache<P>::FillImageViews(DescriptorTable<TICEntry>& table,
|
void TextureCache<P>::FillImageViews(DescriptorTable<TICEntry>& table,
|
||||||
std::span<ImageViewId> cached_image_view_ids,
|
std::span<ImageViewId> cached_image_view_ids,
|
||||||
std::span<ImageViewInOut> views) {
|
std::span<ImageViewInOut> views) {
|
||||||
bool has_blacklisted = false;
|
bool has_blacklisted;
|
||||||
do {
|
do {
|
||||||
has_deleted_images = false;
|
has_deleted_images = false;
|
||||||
if constexpr (has_blacklists) {
|
if constexpr (has_blacklists) {
|
||||||
|
@ -1763,7 +1763,7 @@ void TextureCache<P>::SynchronizeAliases(ImageId image_id) {
|
||||||
});
|
});
|
||||||
const auto& resolution = Settings::values.resolution_info;
|
const auto& resolution = Settings::values.resolution_info;
|
||||||
for (const AliasedImage* const aliased : aliased_images) {
|
for (const AliasedImage* const aliased : aliased_images) {
|
||||||
if (!resolution.active || !any_rescaled) {
|
if (!resolution.active | !any_rescaled) {
|
||||||
CopyImage(image_id, aliased->id, aliased->copies);
|
CopyImage(image_id, aliased->id, aliased->copies);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1774,7 +1774,19 @@ void TextureCache<P>::SynchronizeAliases(ImageId image_id) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ScaleUp(aliased_image);
|
ScaleUp(aliased_image);
|
||||||
CopyImage(image_id, aliased->id, aliased->copies);
|
|
||||||
|
const bool both_2d{image.info.type == ImageType::e2D &&
|
||||||
|
aliased_image.info.type == ImageType::e2D};
|
||||||
|
auto copies = aliased->copies;
|
||||||
|
for (auto copy : copies) {
|
||||||
|
copy.extent.width = std::max<u32>(
|
||||||
|
(copy.extent.width * resolution.up_scale) >> resolution.down_shift, 1);
|
||||||
|
if (both_2d) {
|
||||||
|
copy.extent.height = std::max<u32>(
|
||||||
|
(copy.extent.height * resolution.up_scale) >> resolution.down_shift, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CopyImage(image_id, aliased->id, copies);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue