Compare commits

..

13 Commits

Author SHA1 Message Date
Morph
af89f7683d externals: Update dynarmic to 28714ee7
Reduces compilation times on MSVC.
2021-12-30 22:28:27 -05:00
bunnei
279c7bcc1a Merge pull request #7618 from goldenx86/patch-4
Increase boost requirement to 1.78.0
2021-12-28 16:25:37 -08:00
Matías Locatti
c7235e67ef Empty spaces 2021-12-28 18:50:51 -03:00
Matías Locatti
840d5520d2 Changes to avoid warnings in SSE4.2 optimized SPIR-V 2021-12-28 17:35:55 -03:00
bunnei
f67605e6aa Merge pull request #7622 from ameerj/vk-rescale-invalid-ptr
vk_texture_cache: Fix invalidated pointer access
2021-12-28 00:46:37 -08:00
bunnei
9a0648ff0a Merge pull request #7621 from bunnei/set-mem-perm
core: hle: kernel: Implement SetMemoryPermission.
2021-12-27 23:33:11 -08:00
bunnei
c9e4acc4e2 Merge pull request #7630 from ameerj/glasm-get-int
emit_glasm_context_get_set: Fix GetAttribute return value type.
2021-12-27 16:35:11 -08:00
bunnei
292dfac25e Merge pull request #7620 from bunnei/kernel-thread-x18
core: hle: kernel: KThread: X18 should be a cryptographically random number.
2021-12-25 00:42:54 -08:00
ameerj
37addf7a94 emit_glasm_context_get_set: Fix GetAttribute return value type.
GetAttribute expects an F32 result type at the IR level, this fixes the return value of attributes which were not returning an F32
2021-12-24 20:45:07 -05:00
ameerj
481b210c0d vk_texture_cache: Fix invalidated pointer access
The vulkan ImageView held a reference to its source image for rescale status checking. This pointer is sometimes invalidated when the texture cache slot_images container is resized.
To avoid an invalid pointer dereference, the ImageView now holds a reference to the container itself.
2021-12-23 20:55:48 -05:00
bunnei
4e7a6639d2 core: hle: kernel: Implement SetMemoryPermission.
- Not seen in any games yet, but validated with kernel tests.
2021-12-23 01:10:36 -08:00
bunnei
a0c7d93b84 core: hle: kernel: KThread: X18 should be a cryptographically random number.
- This was added with firmware 11.0.0 (https://switchbrew.org/wiki/11.0.0).
    - X18 is OR'd by kernel with 1, to make sure it is odd.
2021-12-23 00:03:39 -08:00
Matías Locatti
e0193e2be5 Increase boost requirement to 1.78.0
Liu's finding, this allows to build yuzu on VS 2022.
Ignore at will.
2021-12-22 16:10:21 -03:00
31 changed files with 135 additions and 155 deletions

View File

@@ -229,7 +229,7 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR YUZU_USE_BUNDLED_BOOST)
include_directories(SYSTEM "${Boost_INCLUDE_DIRS}")
else()
message(STATUS "Boost 1.73.0 or newer not found, falling back to Conan")
list(APPEND CONAN_REQUIRED_LIBS "boost/1.73.0")
list(APPEND CONAN_REQUIRED_LIBS "boost/1.78.0")
endif()
# Attempt to locate any packages that are required and report the missing ones in CONAN_REQUIRED_LIBS

View File

@@ -806,6 +806,33 @@ ResultCode KPageTable::ResetTransferMemory(VAddr addr, std::size_t size) {
KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped));
block_manager->Update(addr, size / PageSize, state, KMemoryPermission::ReadAndWrite);
return ResultSuccess;
}
ResultCode KPageTable::SetMemoryPermission(VAddr addr, std::size_t size,
Svc::MemoryPermission svc_perm) {
const size_t num_pages = size / PageSize;
// Lock the table.
std::lock_guard lock{page_table_lock};
// Verify we can change the memory permission.
KMemoryState old_state;
KMemoryPermission old_perm;
R_TRY(this->CheckMemoryState(
std::addressof(old_state), std::addressof(old_perm), nullptr, addr, size,
KMemoryState::FlagCanReprotect, KMemoryState::FlagCanReprotect, KMemoryPermission::None,
KMemoryPermission::None, KMemoryAttribute::All, KMemoryAttribute::None));
// Determine new perm.
const KMemoryPermission new_perm = ConvertToKMemoryPermission(svc_perm);
R_SUCCEED_IF(old_perm == new_perm);
// Perform mapping operation.
R_TRY(Operate(addr, num_pages, new_perm, OperationType::ChangePermissions));
// Update the blocks.
block_manager->Update(addr, num_pages, old_state, new_perm, KMemoryAttribute::None);
return ResultSuccess;
}

View File

@@ -47,6 +47,7 @@ public:
KMemoryInfo QueryInfo(VAddr addr);
ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm);
ResultCode ResetTransferMemory(VAddr addr, std::size_t size);
ResultCode SetMemoryPermission(VAddr addr, std::size_t size, Svc::MemoryPermission perm);
ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask,
KMemoryAttribute value);
ResultCode SetHeapCapacity(std::size_t new_heap_capacity);

View File

@@ -26,6 +26,7 @@
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/k_system_control.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_thread_queue.h"
#include "core/hle/kernel/kernel.h"
@@ -50,6 +51,7 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context,
VAddr entry_point, u64 arg) {
context = {};
context.cpu_registers[0] = arg;
context.cpu_registers[18] = Kernel::KSystemControl::GenerateRandomU64() | 1;
context.pc = entry_point;
context.sp = stack_top;
// TODO(merry): Perform a hardware test to determine the below value.

View File

@@ -164,6 +164,36 @@ static ResultCode SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_s
return result;
}
constexpr bool IsValidSetMemoryPermission(MemoryPermission perm) {
switch (perm) {
case MemoryPermission::None:
case MemoryPermission::Read:
case MemoryPermission::ReadWrite:
return true;
default:
return false;
}
}
static ResultCode SetMemoryPermission(Core::System& system, VAddr address, u64 size,
MemoryPermission perm) {
// Validate address / size.
R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
R_UNLESS(size > 0, ResultInvalidSize);
R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
// Validate the permission.
R_UNLESS(IsValidSetMemoryPermission(perm), ResultInvalidNewMemoryPermission);
// Validate that the region is in range for the current process.
auto& page_table = system.Kernel().CurrentProcess()->PageTable();
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
// Set the memory attribute.
return page_table.SetMemoryPermission(address, size, perm);
}
static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask,
u32 attribute) {
LOG_DEBUG(Kernel_SVC,
@@ -2724,7 +2754,7 @@ static const FunctionDef SVC_Table_32[] = {
static const FunctionDef SVC_Table_64[] = {
{0x00, nullptr, "Unknown"},
{0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"},
{0x02, nullptr, "SetMemoryPermission"},
{0x02, SvcWrap64<SetMemoryPermission>, "SetMemoryPermission"},
{0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"},
{0x04, SvcWrap64<MapMemory>, "MapMemory"},
{0x05, SvcWrap64<UnmapMemory>, "UnmapMemory"},

View File

@@ -249,6 +249,14 @@ void SvcWrap64(Core::System& system) {
func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw);
}
// Used by SetMemoryPermission
template <ResultCode func(Core::System&, u64, u64, Svc::MemoryPermission)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
static_cast<Svc::MemoryPermission>(Param(system, 2)))
.raw);
}
// Used by MapSharedMemory
template <ResultCode func(Core::System&, Handle, u64, u64, Svc::MemoryPermission)>
void SvcWrap64(Core::System& system) {

View File

@@ -86,7 +86,7 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal
}
switch (attr) {
case IR::Attribute::PrimitiveId:
ctx.Add("MOV.S {}.x,primitive.id;", inst);
ctx.Add("MOV.F {}.x,primitive.id;", inst);
break;
case IR::Attribute::PositionX:
case IR::Attribute::PositionY:
@@ -113,35 +113,19 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal
ctx.Add("MOV.F {}.x,vertex.tesscoord.{};", inst, swizzle);
break;
case IR::Attribute::InstanceId:
ctx.Add("MOV.S {}.x,{}.instance;", inst, ctx.attrib_name);
ctx.Add("MOV.F {}.x,{}.instance;", inst, ctx.attrib_name);
break;
case IR::Attribute::VertexId:
ctx.Add("MOV.S {}.x,{}.id;", inst, ctx.attrib_name);
ctx.Add("MOV.F {}.x,{}.id;", inst, ctx.attrib_name);
break;
case IR::Attribute::FrontFace:
ctx.Add("CMP.S {}.x,{}.facing.x,0,-1;", inst, ctx.attrib_name);
ctx.Add("CMP.F {}.x,{}.facing.x,0,-1;", inst, ctx.attrib_name);
break;
default:
throw NotImplementedException("Get attribute {}", attr);
}
}
void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32) {
switch (attr) {
case IR::Attribute::PrimitiveId:
ctx.Add("MOV.S {}.x,primitive.id;", inst);
break;
case IR::Attribute::InstanceId:
ctx.Add("MOV.S {}.x,{}.instance;", inst, ctx.attrib_name);
break;
case IR::Attribute::VertexId:
ctx.Add("MOV.S {}.x,{}.id;", inst, ctx.attrib_name);
break;
default:
throw NotImplementedException("Get U32 attribute {}", attr);
}
}
void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value,
[[maybe_unused]] ScalarU32 vertex) {
const u32 element{static_cast<u32>(attr) % 4};

View File

@@ -50,7 +50,6 @@ void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset);
void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset);
void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32 vertex);
void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32 vertex);
void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, ScalarU32 vertex);
void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, ScalarS32 offset, ScalarU32 vertex);
void EmitSetAttributeIndexed(EmitContext& ctx, ScalarU32 offset, ScalarF32 value, ScalarU32 vertex);

View File

@@ -7,7 +7,6 @@
#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
#include "shader_recompiler/frontend/ir/value.h"
#include "shader_recompiler/profile.h"
namespace Shader::Backend::GLSL {
namespace {
@@ -31,9 +30,8 @@ void EmitConditionRef(EmitContext& ctx, IR::Inst& inst, const IR::Value& value)
inst.DestructiveAddUsage(1);
const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U1)};
const auto input{ctx.var_alloc.Consume(value)};
const auto suffix{ctx.profile.has_gl_bool_ref_bug ? "?true:false" : ""};
if (ret != input) {
ctx.Add("{}={}{};", ret, input, suffix);
ctx.Add("{}={};", ret, input);
}
}

View File

@@ -102,46 +102,39 @@ void GetCbuf16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, const
void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
const IR::Value& offset) {
const auto cast{ctx.profile.has_gl_cbuf_ftou_bug ? "" : "ftou"};
GetCbuf8(ctx, inst, binding, offset, cast);
GetCbuf8(ctx, inst, binding, offset, "ftou");
}
void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
const IR::Value& offset) {
const auto cast{ctx.profile.has_gl_cbuf_ftou_bug ? "int" : "ftoi"};
GetCbuf8(ctx, inst, binding, offset, cast);
GetCbuf8(ctx, inst, binding, offset, "ftoi");
}
void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
const IR::Value& offset) {
const auto cast{ctx.profile.has_gl_cbuf_ftou_bug ? "" : "ftou"};
GetCbuf16(ctx, inst, binding, offset, cast);
GetCbuf16(ctx, inst, binding, offset, "ftou");
}
void EmitGetCbufS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
const IR::Value& offset) {
const auto cast{ctx.profile.has_gl_cbuf_ftou_bug ? "int" : "ftoi"};
GetCbuf16(ctx, inst, binding, offset, cast);
GetCbuf16(ctx, inst, binding, offset, "ftoi");
}
void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
const IR::Value& offset) {
const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)};
const auto cast{ctx.profile.has_gl_cbuf_ftou_bug ? "" : "ftou"};
GetCbuf(ctx, ret, binding, offset, 32, cast);
GetCbuf(ctx, ret, binding, offset, 32, "ftou");
}
void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
const IR::Value& offset) {
const auto ret{ctx.var_alloc.Define(inst, GlslVarType::F32)};
const auto cast{ctx.profile.has_gl_cbuf_ftou_bug ? "utof" : ""};
GetCbuf(ctx, ret, binding, offset, 32, cast);
GetCbuf(ctx, ret, binding, offset, 32);
}
void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
const IR::Value& offset) {
const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())};
const auto cast{ctx.profile.has_gl_cbuf_ftou_bug ? "" : "ftou"};
if (offset.IsImmediate()) {
static constexpr u32 cbuf_size{0x10000};
const u32 u32_offset{offset.U32()};
@@ -152,26 +145,26 @@ void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding
return;
}
if (u32_offset % 2 == 0) {
ctx.AddU32x2("{}={}({}[{}].{}{});", inst, cast, cbuf, u32_offset / 16,
ctx.AddU32x2("{}=ftou({}[{}].{}{});", inst, cbuf, u32_offset / 16,
OffsetSwizzle(u32_offset), OffsetSwizzle(u32_offset + 4));
} else {
ctx.AddU32x2("{}=uvec2({}({}[{}].{}),{}({}[{}].{}));", inst, cast, cbuf,
u32_offset / 16, OffsetSwizzle(u32_offset), cast, cbuf,
(u32_offset + 4) / 16, OffsetSwizzle(u32_offset + 4));
ctx.AddU32x2("{}=uvec2(ftou({}[{}].{}),ftou({}[{}].{}));", inst, cbuf, u32_offset / 16,
OffsetSwizzle(u32_offset), cbuf, (u32_offset + 4) / 16,
OffsetSwizzle(u32_offset + 4));
}
return;
}
const auto offset_var{ctx.var_alloc.Consume(offset)};
if (!ctx.profile.has_gl_component_indexing_bug) {
ctx.AddU32x2("{}=uvec2({}({}[{}>>4][({}>>2)%4]),{}({}[({}+4)>>4][(({}+4)>>2)%4]));", inst,
cast, cbuf, offset_var, offset_var, cast, cbuf, offset_var, offset_var);
ctx.AddU32x2("{}=uvec2(ftou({}[{}>>4][({}>>2)%4]),ftou({}[({}+4)>>4][(({}+4)>>2)%4]));",
inst, cbuf, offset_var, offset_var, cbuf, offset_var, offset_var);
return;
}
const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32x2)};
const auto cbuf_offset{fmt::format("{}>>2", offset_var)};
for (u32 swizzle = 0; swizzle < 4; ++swizzle) {
ctx.Add("if(({}&3)=={}){}=uvec2({}({}[{}>>4].{}),{}({}[({}+4)>>4].{}));", cbuf_offset,
swizzle, ret, cast, cbuf, offset_var, "xyzw"[swizzle], cast, cbuf, offset_var,
ctx.Add("if(({}&3)=={}){}=uvec2(ftou({}[{}>>4].{}),ftou({}[({}+4)>>4].{}));", cbuf_offset,
swizzle, ret, cbuf, offset_var, "xyzw"[swizzle], cbuf, offset_var,
"xyzw"[(swizzle + 1) % 4]);
}
}
@@ -228,22 +221,6 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
}
}
void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, std::string_view) {
switch (attr) {
case IR::Attribute::PrimitiveId:
ctx.AddU32("{}=uint(gl_PrimitiveID);", inst);
break;
case IR::Attribute::InstanceId:
ctx.AddU32("{}=uint(gl_InstanceID);", inst);
break;
case IR::Attribute::VertexId:
ctx.AddU32("{}=uint(gl_VertexID);", inst);
break;
default:
throw NotImplementedException("Get U32 attribute {}", attr);
}
}
void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value,
[[maybe_unused]] std::string_view vertex) {
if (IR::IsGeneric(attr)) {

View File

@@ -125,11 +125,11 @@ void EmitFPNeg16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i
}
void EmitFPNeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
ctx.AddF32("{}=0.f-({});", inst, value);
ctx.AddF32("{}=-({});", inst, value);
}
void EmitFPNeg64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
ctx.AddF64("{}=double(0.)-({});", inst, value);
ctx.AddF64("{}=-({});", inst, value);
}
void EmitFPSin(EmitContext& ctx, IR::Inst& inst, std::string_view value) {

View File

@@ -60,8 +60,6 @@ void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding
const IR::Value& offset);
void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
std::string_view vertex);
void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
std::string_view vertex);
void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value,
std::string_view vertex);
void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, std::string_view offset,

View File

@@ -87,11 +87,11 @@ void EmitUDiv32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::strin
}
void EmitINeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
ctx.AddU32("{}=uint(int(0)-int({}));", inst, value);
ctx.AddU32("{}=uint(-({}));", inst, value);
}
void EmitINeg64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
ctx.AddU64("{}=uint64_t(int64_t(0)-int64_t({}));", inst, value);
ctx.AddU64("{}=-({});", inst, value);
}
void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {

View File

@@ -90,9 +90,7 @@ void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value&
if (phi_reg == val_reg) {
return;
}
const bool needs_workaround{ctx.profile.has_gl_bool_ref_bug && phi_type == IR::Type::U1};
const auto suffix{needs_workaround ? "?true:false" : ""};
ctx.Add("{}={}{};", phi_reg, val_reg, suffix);
ctx.Add("{}={};", phi_reg, val_reg);
}
void EmitPrologue(EmitContext& ctx) {

View File

@@ -428,10 +428,9 @@ void EmitContext::DefineConstantBuffers(Bindings& bindings) {
return;
}
for (const auto& desc : info.constant_buffer_descriptors) {
const auto cbuf_type{profile.has_gl_cbuf_ftou_bug ? "uvec4" : "vec4"};
header += fmt::format("layout(std140,binding={}) uniform {}_cbuf_{}{{{} {}_cbuf{}[{}];}};",
bindings.uniform_buffer, stage_name, desc.index, cbuf_type,
stage_name, desc.index, 4 * 1024);
header += fmt::format(
"layout(std140,binding={}) uniform {}_cbuf_{}{{vec4 {}_cbuf{}[{}];}};",
bindings.uniform_buffer, stage_name, desc.index, stage_name, desc.index, 4 * 1024);
bindings.uniform_buffer += desc.count;
}
}

View File

@@ -30,11 +30,20 @@ struct FuncTraits<ReturnType_ (*)(Args...)> {
using ArgType = std::tuple_element_t<I, std::tuple<Args...>>;
};
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4702) // Ignore unreachable code warning
#endif
template <auto func, typename... Args>
void SetDefinition(EmitContext& ctx, IR::Inst* inst, Args... args) {
inst->SetDefinition<Id>(func(ctx, std::forward<Args>(args)...));
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
template <typename ArgType>
ArgType Arg(EmitContext& ctx, const IR::Value& arg) {
if constexpr (std::is_same_v<ArgType, Id>) {

View File

@@ -355,31 +355,6 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) {
}
}
Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, Id) {
switch (attr) {
case IR::Attribute::PrimitiveId:
return ctx.OpLoad(ctx.U32[1], ctx.primitive_id);
case IR::Attribute::InstanceId:
if (ctx.profile.support_vertex_instance_id) {
return ctx.OpLoad(ctx.U32[1], ctx.instance_id);
} else {
const Id index{ctx.OpLoad(ctx.U32[1], ctx.instance_index)};
const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_instance)};
return ctx.OpISub(ctx.U32[1], index, base);
}
case IR::Attribute::VertexId:
if (ctx.profile.support_vertex_instance_id) {
return ctx.OpLoad(ctx.U32[1], ctx.vertex_id);
} else {
const Id index{ctx.OpLoad(ctx.U32[1], ctx.vertex_index)};
const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)};
return ctx.OpISub(ctx.U32[1], index, base);
}
default:
throw NotImplementedException("Read U32 attribute {}", attr);
}
}
void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, [[maybe_unused]] Id vertex) {
const std::optional<OutAttr> output{OutputAttrPointer(ctx, attr)};
if (!output) {

View File

@@ -53,7 +53,6 @@ Id EmitGetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& o
Id EmitGetCbufF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset);
Id EmitGetCbufU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset);
Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex);
Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, Id vertex);
void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, Id vertex);
Id EmitGetAttributeIndexed(EmitContext& ctx, Id offset, Id vertex);
void EmitSetAttributeIndexed(EmitContext& ctx, Id offset, Id value, Id vertex);

View File

@@ -40,7 +40,6 @@ OPCODE(GetCbufU32, U32, U32,
OPCODE(GetCbufF32, F32, U32, U32, )
OPCODE(GetCbufU32x2, U32x2, U32, U32, )
OPCODE(GetAttribute, F32, Attribute, U32, )
OPCODE(GetAttributeU32, U32, Attribute, U32, )
OPCODE(SetAttribute, Void, Attribute, F32, U32, )
OPCODE(GetAttributeIndexed, F32, U32, U32, )
OPCODE(SetAttributeIndexed, Void, U32, F32, U32, )

View File

@@ -389,7 +389,6 @@ void VisitUsages(Info& info, IR::Inst& inst) {
info.uses_demote_to_helper_invocation = true;
break;
case IR::Opcode::GetAttribute:
case IR::Opcode::GetAttributeU32:
info.loads.mask[static_cast<size_t>(inst.Arg(0).Attribute())] = true;
break;
case IR::Opcode::SetAttribute:

View File

@@ -505,29 +505,6 @@ void FoldBitCast(IR::Inst& inst, IR::Opcode reverse) {
return;
}
}
if constexpr (op == IR::Opcode::BitCastU32F32) {
// Workaround for new NVIDIA driver bug, where:
// uint attr = ftou(itof(gl_InstanceID));
// always returned 0.
// We can instead manually optimize this and work around the driver bug:
// uint attr = uint(gl_InstanceID);
if (arg_inst->GetOpcode() == IR::Opcode::GetAttribute) {
const IR::Attribute attr{arg_inst->Arg(0).Attribute()};
switch (attr) {
case IR::Attribute::PrimitiveId:
case IR::Attribute::InstanceId:
case IR::Attribute::VertexId:
break;
default:
return;
}
// Replace the bitcasts with an integer attribute get
inst.ReplaceOpcode(IR::Opcode::GetAttributeU32);
inst.SetArg(0, arg_inst->Arg(0));
inst.SetArg(1, arg_inst->Arg(1));
return;
}
}
}
void FoldInverseFunc(IR::Inst& inst, IR::Opcode reverse) {

View File

@@ -65,10 +65,6 @@ struct Profile {
bool has_gl_component_indexing_bug{};
/// The precise type qualifier is broken in the fragment stage of some drivers
bool has_gl_precise_bug{};
/// Some drivers do not properly support floatBitsToUint when used on cbufs
bool has_gl_cbuf_ftou_bug{};
/// Some drivers poorly optimize boolean variable references
bool has_gl_bool_ref_bug{};
/// Ignores SPIR-V ordered vs unordered using GLSL semantics
bool ignore_nan_fp_comparisons{};

View File

@@ -182,13 +182,17 @@ Device::Device() {
shader_backend = Settings::ShaderBackend::GLSL;
}
if (shader_backend == Settings::ShaderBackend::GLSL && is_nvidia) {
if (shader_backend == Settings::ShaderBackend::GLSL && is_nvidia &&
!Settings::values.renderer_debug) {
const std::string_view driver_version = version.substr(13);
const int version_major =
std::atoi(driver_version.substr(0, driver_version.find(".")).data());
if (version_major >= 495) {
has_cbuf_ftou_bug = true;
has_bool_ref_bug = true;
LOG_WARNING(Render_OpenGL, "NVIDIA drivers 495 and later causes significant problems "
"with yuzu. Forcing GLASM as a mitigation.");
shader_backend = Settings::ShaderBackend::GLASM;
use_assembly_shaders = true;
}
}

View File

@@ -152,14 +152,6 @@ public:
return need_fastmath_off;
}
bool HasCbufFtouBug() const {
return has_cbuf_ftou_bug;
}
bool HasBoolRefBug() const {
return has_bool_ref_bug;
}
Settings::ShaderBackend GetShaderBackend() const {
return shader_backend;
}
@@ -208,8 +200,6 @@ private:
bool has_sparse_texture_2{};
bool warp_size_potentially_larger_than_guest{};
bool need_fastmath_off{};
bool has_cbuf_ftou_bug{};
bool has_bool_ref_bug{};
std::string vendor_name;
};

View File

@@ -214,8 +214,6 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
.has_broken_fp16_float_controls = false,
.has_gl_component_indexing_bug = device.HasComponentIndexingBug(),
.has_gl_precise_bug = device.HasPreciseBug(),
.has_gl_cbuf_ftou_bug = device.HasCbufFtouBug(),
.has_gl_bool_ref_bug = device.HasBoolRefBug(),
.ignore_nan_fp_comparisons = true,
.gl_max_compute_smem_size = device.GetMaxComputeSharedMemorySize(),
},

View File

@@ -1047,7 +1047,7 @@ bool Image::ScaleDown(bool ignore) {
}
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
ImageId image_id_, Image& image)
ImageId image_id_, Image& image, const SlotVector<Image>&)
: VideoCommon::ImageViewBase{info, image.info, image_id_}, views{runtime.null_image_views} {
const Device& device = runtime.device;
if (True(image.flags & ImageFlagBits::Converted)) {

View File

@@ -36,6 +36,7 @@ using VideoCommon::ImageViewType;
using VideoCommon::NUM_RT;
using VideoCommon::Region2D;
using VideoCommon::RenderTargets;
using VideoCommon::SlotVector;
struct ImageBufferMap {
~ImageBufferMap();
@@ -234,7 +235,8 @@ class ImageView : public VideoCommon::ImageViewBase {
friend Image;
public:
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&);
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&,
const SlotVector<Image>&);
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&,
const VideoCommon::ImageViewInfo&, GPUVAddr);
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,

View File

@@ -1473,8 +1473,7 @@ bool Image::BlitScaleHelper(bool scale_up) {
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
ImageId image_id_, Image& image)
: VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device},
src_image{&image}, image_handle{image.Handle()},
samples(ConvertSampleCount(image.info.num_samples)) {
image_handle{image.Handle()}, samples(ConvertSampleCount(image.info.num_samples)) {
using Shader::TextureType;
const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info);
@@ -1557,6 +1556,12 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
}
}
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
ImageId image_id_, Image& image, const SlotVector<Image>& slot_imgs)
: ImageView{runtime, info, image_id_, image} {
slot_images = &slot_imgs;
}
ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
const VideoCommon::ImageViewInfo& view_info, GPUVAddr gpu_addr_)
: VideoCommon::ImageViewBase{info, view_info}, gpu_addr{gpu_addr_},
@@ -1613,10 +1618,12 @@ VkImageView ImageView::StorageView(Shader::TextureType texture_type,
}
bool ImageView::IsRescaled() const noexcept {
if (!src_image) {
if (!slot_images) {
return false;
}
return src_image->IsRescaled();
const auto& slots = *slot_images;
const auto& src_image = slots[image_id];
return src_image.IsRescaled();
}
vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) {

View File

@@ -23,6 +23,7 @@ using VideoCommon::ImageId;
using VideoCommon::NUM_RT;
using VideoCommon::Region2D;
using VideoCommon::RenderTargets;
using VideoCommon::SlotVector;
using VideoCore::Surface::PixelFormat;
class ASTCDecoderPass;
@@ -170,6 +171,8 @@ private:
class ImageView : public VideoCommon::ImageViewBase {
public:
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&);
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&,
const SlotVector<Image>&);
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&,
const VideoCommon::ImageViewInfo&, GPUVAddr);
explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&);
@@ -226,7 +229,7 @@ private:
[[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask);
const Device* device = nullptr;
const Image* src_image{};
const SlotVector<Image>* slot_images = nullptr;
std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views;
std::unique_ptr<StorageViews> storage_views;

View File

@@ -1397,7 +1397,8 @@ ImageViewId TextureCache<P>::FindOrEmplaceImageView(ImageId image_id, const Imag
if (const ImageViewId image_view_id = image.FindView(info); image_view_id) {
return image_view_id;
}
const ImageViewId image_view_id = slot_image_views.insert(runtime, info, image_id, image);
const ImageViewId image_view_id =
slot_image_views.insert(runtime, info, image_id, image, slot_images);
image.InsertView(info, image_view_id);
return image_view_id;
}