Compare commits

...

18 Commits

Author SHA1 Message Date
yuzubot
0ab1c0e056 Android #167 2023-12-21 00:57:06 +00:00
yuzubot
23c62f26d5 Merge PR 12410 2023-12-21 00:57:06 +00:00
yuzubot
1019fbca95 Merge PR 12407 2023-12-21 00:57:06 +00:00
liamwhite
bedc758fe7 Merge pull request #12414 from jbeich/vk274
externals: update Vulkan-Headers to v1.3.274
2023-12-20 12:46:50 -05:00
liamwhite
76701185ad Merge pull request #12400 from ameerj/vk-query-prefix-fix
vk_query_cache: Fix prefix sum max_accumulation_limit logic
2023-12-20 12:46:41 -05:00
Fernando S
f1cb14eb54 Merge pull request #12417 from liamwhite/arm64-gcc-fix
nce: hide shadowing warnings from dynarmic headers
2023-12-20 18:46:08 +01:00
Fernando S
f4f4a469a9 Merge pull request #12409 from liamwhite/bits-and-bytes
nce: fix read size in simd immediate emulation
2023-12-20 18:45:44 +01:00
Fernando S
9e5b4052ed Merge pull request #12403 from liamwhite/clipdistance
shader_recompiler: use minimal clip distance array
2023-12-20 18:45:20 +01:00
Fernando S
234867b84d Merge pull request #12390 from liamwhite/binding-insanity
renderer_vulkan: work around turnip binding bug in a610
2023-12-20 18:44:47 +01:00
Liam
4b60aec190 nce: hide shadowing warnings from dynarmic headers 2023-12-20 11:07:50 -05:00
Jan Beich
ecfba79d98 externals: update Vulkan-Headers to v1.3.274 2023-12-20 01:13:09 +01:00
Jan Beich
310834aea2 vulkan_common: unbreak build with Vulkan-Headers 1.3.274
src/video_core/vulkan_common/vulkan_wrapper.cpp:293:13: error: enumeration value 'VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR' not handled in switch [-Werror,-Wswitch]
    switch (result) {
            ^~~~~~
2023-12-20 01:12:41 +01:00
Liam
93c19a40bf nce: increase handler stack size 2023-12-19 15:24:13 -05:00
Liam
a94721fde0 nce: fix read size in simd immediate emulation 2023-12-19 12:51:19 -05:00
Liam
fcfa8b680b shader_recompiler: use minimal clip distance array 2023-12-18 22:25:14 -05:00
Liam
94244437de shader_recompiler: ignore clip distances beyond driver support level 2023-12-18 22:25:14 -05:00
Ameer J
a2b567dfd6 vk_query_cache: Fix prefix sum max_accumulation_limit logic 2023-12-18 12:37:55 -05:00
Liam
fba3fa705d renderer_vulkan: work around turnip binding bug in a610 2023-12-17 15:45:09 -05:00
23 changed files with 149 additions and 37 deletions

View File

@@ -305,7 +305,7 @@ find_package(ZLIB 1.2 REQUIRED)
find_package(zstd 1.5 REQUIRED) find_package(zstd 1.5 REQUIRED)
if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS) if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS)
find_package(Vulkan 1.3.256 REQUIRED) find_package(Vulkan 1.3.274 REQUIRED)
endif() endif()
if (ENABLE_LIBUSB) if (ENABLE_LIBUSB)

View File

@@ -1,3 +1,13 @@
| Pull Request | Commit | Title | Author | Merged? |
|----|----|----|----|----|
| [12407](https://github.com/yuzu-emu/yuzu//pull/12407) | [`6e2cbd474`](https://github.com/yuzu-emu/yuzu//pull/12407/files) | shader_recompiler: patch small float image writes on broken drivers | [liamwhite](https://github.com/liamwhite/) | Yes |
| [12410](https://github.com/yuzu-emu/yuzu//pull/12410) | [`d0a75580d`](https://github.com/yuzu-emu/yuzu//pull/12410/files) | renderer_vulkan: don't pass null view when nullDescriptor is not supported | [liamwhite](https://github.com/liamwhite/) | Yes |
End of merge log. You can find the original README.md below the break.
-----
<!-- <!--
SPDX-FileCopyrightText: 2018 yuzu Emulator Project SPDX-FileCopyrightText: 2018 yuzu Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later SPDX-License-Identifier: GPL-2.0-or-later

View File

@@ -39,7 +39,7 @@ fpsimd_context* GetFloatingPointState(mcontext_t& host_ctx) {
} }
using namespace Common::Literals; using namespace Common::Literals;
constexpr u32 StackSize = 32_KiB; constexpr u32 StackSize = 128_KiB;
} // namespace } // namespace

View File

@@ -5,8 +5,6 @@
#include "common/bit_cast.h" #include "common/bit_cast.h"
#include "core/arm/nce/interpreter_visitor.h" #include "core/arm/nce/interpreter_visitor.h"
#include <dynarmic/frontend/A64/decoder/a64.h>
namespace Core { namespace Core {
template <u32 BitSize> template <u32 BitSize>
@@ -249,6 +247,7 @@ bool InterpreterVisitor::LDR_lit_fpsimd(Imm<2> opc, Imm<19> imm19, Vec Vt) {
return false; return false;
} }
// Size in bytes
const u64 size = 4 << opc.ZeroExtend(); const u64 size = 4 << opc.ZeroExtend();
const u64 offset = imm19.SignExtend<u64>() << 2; const u64 offset = imm19.SignExtend<u64>() << 2;
const u64 address = this->GetPc() + offset; const u64 address = this->GetPc() + offset;
@@ -530,7 +529,7 @@ bool InterpreterVisitor::SIMDImmediate(bool wback, bool postindex, size_t scale,
} }
case MemOp::Load: { case MemOp::Load: {
u128 data{}; u128 data{};
m_memory.ReadBlock(address, &data, datasize); m_memory.ReadBlock(address, &data, datasize / 8);
this->SetVec(Vt, data); this->SetVec(Vt, data);
break; break;
} }

View File

@@ -4,9 +4,15 @@
#pragma once #pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#include <dynarmic/frontend/A64/a64_types.h> #include <dynarmic/frontend/A64/a64_types.h>
#include <dynarmic/frontend/A64/decoder/a64.h>
#include <dynarmic/frontend/imm.h> #include <dynarmic/frontend/imm.h>
#pragma GCC diagnostic pop
namespace Core { namespace Core {
class VisitorBase { class VisitorBase {

View File

@@ -74,6 +74,11 @@ std::optional<OutAttr> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) {
case IR::Attribute::ClipDistance7: { case IR::Attribute::ClipDistance7: {
const u32 base{static_cast<u32>(IR::Attribute::ClipDistance0)}; const u32 base{static_cast<u32>(IR::Attribute::ClipDistance0)};
const u32 index{static_cast<u32>(attr) - base}; const u32 index{static_cast<u32>(attr) - base};
if (index >= ctx.profile.max_user_clip_distances) {
LOG_WARNING(Shader, "Ignoring clip distance store {} >= {} supported", index,
ctx.profile.max_user_clip_distances);
return std::nullopt;
}
const Id clip_num{ctx.Const(index)}; const Id clip_num{ctx.Const(index)};
return OutputAccessChain(ctx, ctx.output_f32, ctx.clip_distances, clip_num); return OutputAccessChain(ctx, ctx.output_f32, ctx.clip_distances, clip_num);
} }

View File

@@ -74,9 +74,17 @@ spv::ImageFormat GetImageFormat(ImageFormat format) {
throw InvalidArgument("Invalid image format {}", format); throw InvalidArgument("Invalid image format {}", format);
} }
Id GetImageSampledType(EmitContext& ctx, const ImageDescriptor& desc) {
if (desc.is_float) {
return ctx.F32[1];
} else {
return ctx.U32[1];
}
}
Id ImageType(EmitContext& ctx, const ImageDescriptor& desc) { Id ImageType(EmitContext& ctx, const ImageDescriptor& desc) {
const spv::ImageFormat format{GetImageFormat(desc.format)}; const spv::ImageFormat format{GetImageFormat(desc.format)};
const Id type{ctx.U32[1]}; const Id type{GetImageSampledType(ctx, desc)};
switch (desc.type) { switch (desc.type) {
case TextureType::Color1D: case TextureType::Color1D:
return ctx.TypeImage(type, spv::Dim::Dim1D, false, false, false, 2, format); return ctx.TypeImage(type, spv::Dim::Dim1D, false, false, false, 2, format);
@@ -1528,7 +1536,8 @@ void EmitContext::DefineOutputs(const IR::Program& program) {
if (stage == Stage::Fragment) { if (stage == Stage::Fragment) {
throw NotImplementedException("Storing ClipDistance in fragment stage"); throw NotImplementedException("Storing ClipDistance in fragment stage");
} }
const Id type{TypeArray(F32[1], Const(8U))}; const Id type{TypeArray(
F32[1], Const(std::min(info.used_clip_distances, profile.max_user_clip_distances)))};
clip_distances = DefineOutput(*this, type, invocations, spv::BuiltIn::ClipDistance); clip_distances = DefineOutput(*this, type, invocations, spv::BuiltIn::ClipDistance);
} }
if (info.stores[IR::Attribute::Layer] && if (info.stores[IR::Attribute::Layer] &&

View File

@@ -512,7 +512,7 @@ OPCODE(ImageQueryDimensions, U32x4, Opaq
OPCODE(ImageQueryLod, F32x4, Opaque, Opaque, ) OPCODE(ImageQueryLod, F32x4, Opaque, Opaque, )
OPCODE(ImageGradient, F32x4, Opaque, Opaque, Opaque, Opaque, Opaque, ) OPCODE(ImageGradient, F32x4, Opaque, Opaque, Opaque, Opaque, Opaque, )
OPCODE(ImageRead, U32x4, Opaque, Opaque, ) OPCODE(ImageRead, U32x4, Opaque, Opaque, )
OPCODE(ImageWrite, Void, Opaque, Opaque, U32x4, ) OPCODE(ImageWrite, Void, Opaque, Opaque, Opaque, )
OPCODE(IsTextureScaled, U1, U32, ) OPCODE(IsTextureScaled, U1, U32, )
OPCODE(IsImageScaled, U1, U32, ) OPCODE(IsImageScaled, U1, U32, )

View File

@@ -21,6 +21,8 @@ struct HostTranslateInfo {
///< passthrough shaders ///< passthrough shaders
bool support_conditional_barrier{}; ///< True when the device supports barriers in conditional bool support_conditional_barrier{}; ///< True when the device supports barriers in conditional
///< control flow ///< control flow
bool support_ufloat_write_as_uint{}; ///< True when the device supports writing float images
///< as bitcasts to uint
}; };
} // namespace Shader } // namespace Shader

View File

@@ -913,7 +913,11 @@ void GatherInfoFromHeader(Environment& env, Info& info) {
} }
for (size_t index = 0; index < 8; ++index) { for (size_t index = 0; index < 8; ++index) {
const u16 mask{header.vtg.omap_systemc.clip_distances}; const u16 mask{header.vtg.omap_systemc.clip_distances};
info.stores.Set(IR::Attribute::ClipDistance0 + index, ((mask >> index) & 1) != 0); const bool used{((mask >> index) & 1) != 0};
info.stores.Set(IR::Attribute::ClipDistance0 + index, used);
if (used) {
info.used_clip_distances = static_cast<u32>(index) + 1;
}
} }
info.stores.Set(IR::Attribute::PrimitiveId, info.stores.Set(IR::Attribute::PrimitiveId,
header.vtg.omap_systemb.primitive_array_id != 0); header.vtg.omap_systemb.primitive_array_id != 0);

View File

@@ -372,6 +372,10 @@ TexturePixelFormat ReadTexturePixelFormat(Environment& env, const ConstBufferAdd
return env.ReadTexturePixelFormat(GetTextureHandle(env, cbuf)); return env.ReadTexturePixelFormat(GetTextureHandle(env, cbuf));
} }
bool TexturePixelFormatIsFloat(Environment& env, const ConstBufferAddr& cbuf) {
return ReadTexturePixelFormat(env, cbuf) == TexturePixelFormat::B10G11R11_FLOAT;
}
class Descriptors { class Descriptors {
public: public:
explicit Descriptors(TextureBufferDescriptors& texture_buffer_descriptors_, explicit Descriptors(TextureBufferDescriptors& texture_buffer_descriptors_,
@@ -428,8 +432,9 @@ public:
return desc.type == existing.type && desc.format == existing.format && return desc.type == existing.type && desc.format == existing.format &&
desc.cbuf_index == existing.cbuf_index && desc.cbuf_index == existing.cbuf_index &&
desc.cbuf_offset == existing.cbuf_offset && desc.count == existing.count && desc.cbuf_offset == existing.cbuf_offset && desc.count == existing.count &&
desc.size_shift == existing.size_shift; desc.size_shift == existing.size_shift && desc.is_float == existing.is_float;
})}; })};
// TODO: handle is_float?
image_descriptors[index].is_written |= desc.is_written; image_descriptors[index].is_written |= desc.is_written;
image_descriptors[index].is_read |= desc.is_read; image_descriptors[index].is_read |= desc.is_read;
return index; return index;
@@ -500,6 +505,19 @@ void PatchTexelFetch(IR::Block& block, IR::Inst& inst, TexturePixelFormat pixel_
ir.FPMul(ir.ConvertSToF(32, 32, ir.BitCast<IR::U32>(w)), max_value)); ir.FPMul(ir.ConvertSToF(32, 32, ir.BitCast<IR::U32>(w)), max_value));
inst.ReplaceUsesWith(converted); inst.ReplaceUsesWith(converted);
} }
void PatchSmallFloatImageWrite(IR::Block& block, IR::Inst& inst) {
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
const IR::Value old_value{inst.Arg(2)};
const IR::F32 x(ir.BitCast<IR::F32>(IR::U32(ir.CompositeExtract(old_value, 0))));
const IR::F32 y(ir.BitCast<IR::F32>(IR::U32(ir.CompositeExtract(old_value, 1))));
const IR::F32 z(ir.BitCast<IR::F32>(IR::U32(ir.CompositeExtract(old_value, 2))));
const IR::F32 w(ir.BitCast<IR::F32>(IR::U32(ir.CompositeExtract(old_value, 3))));
const IR::Value converted = ir.CompositeConstruct(x, y, z, w);
inst.SetArg(2, converted);
}
} // Anonymous namespace } // Anonymous namespace
void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo& host_info) { void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo& host_info) {
@@ -531,6 +549,9 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
inst->ReplaceOpcode(IndexedInstruction(*inst)); inst->ReplaceOpcode(IndexedInstruction(*inst));
const auto& cbuf{texture_inst.cbuf}; const auto& cbuf{texture_inst.cbuf};
const bool is_float_write{!host_info.support_ufloat_write_as_uint &&
inst->GetOpcode() == IR::Opcode::ImageWrite &&
TexturePixelFormatIsFloat(env, cbuf)};
auto flags{inst->Flags<IR::TextureInstInfo>()}; auto flags{inst->Flags<IR::TextureInstInfo>()};
bool is_multisample{false}; bool is_multisample{false};
switch (inst->GetOpcode()) { switch (inst->GetOpcode()) {
@@ -603,6 +624,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
.format = flags.image_format, .format = flags.image_format,
.is_written = is_written, .is_written = is_written,
.is_read = is_read, .is_read = is_read,
.is_float = is_float_write,
.cbuf_index = cbuf.index, .cbuf_index = cbuf.index,
.cbuf_offset = cbuf.offset, .cbuf_offset = cbuf.offset,
.count = cbuf.count, .count = cbuf.count,
@@ -662,6 +684,10 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
PatchTexelFetch(*texture_inst.block, *texture_inst.inst, pixel_format); PatchTexelFetch(*texture_inst.block, *texture_inst.inst, pixel_format);
} }
} }
if (is_float_write) {
PatchSmallFloatImageWrite(*texture_inst.block, *inst);
}
} }
} }

View File

@@ -87,6 +87,8 @@ struct Profile {
bool has_broken_robust{}; bool has_broken_robust{};
u64 min_ssbo_alignment{}; u64 min_ssbo_alignment{};
u32 max_user_clip_distances{};
}; };
} // namespace Shader } // namespace Shader

View File

@@ -42,6 +42,7 @@ enum class TexturePixelFormat : u32 {
R16G16B16A16_SNORM, R16G16B16A16_SNORM,
R16G16_SNORM, R16G16_SNORM,
R16_SNORM, R16_SNORM,
B10G11R11_FLOAT,
OTHER OTHER
}; };
@@ -129,6 +130,7 @@ struct ImageDescriptor {
ImageFormat format; ImageFormat format;
bool is_written; bool is_written;
bool is_read; bool is_read;
bool is_float;
u32 cbuf_index; u32 cbuf_index;
u32 cbuf_offset; u32 cbuf_offset;
u32 count; u32 count;
@@ -227,6 +229,8 @@ struct Info {
bool requires_layer_emulation{}; bool requires_layer_emulation{};
IR::Attribute emulated_layer{}; IR::Attribute emulated_layer{};
u32 used_clip_distances{};
boost::container::static_vector<ConstantBufferDescriptor, MAX_CBUFS> boost::container::static_vector<ConstantBufferDescriptor, MAX_CBUFS>
constant_buffer_descriptors; constant_buffer_descriptors;
boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors; boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors;

View File

@@ -233,6 +233,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
.ignore_nan_fp_comparisons = true, .ignore_nan_fp_comparisons = true,
.gl_max_compute_smem_size = device.GetMaxComputeSharedMemorySize(), .gl_max_compute_smem_size = device.GetMaxComputeSharedMemorySize(),
.min_ssbo_alignment = device.GetShaderStorageBufferAlignment(), .min_ssbo_alignment = device.GetShaderStorageBufferAlignment(),
.max_user_clip_distances = 8,
}, },
host_info{ host_info{
.support_float64 = true, .support_float64 = true,
@@ -244,6 +245,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
.min_ssbo_alignment = static_cast<u32>(device.GetShaderStorageBufferAlignment()), .min_ssbo_alignment = static_cast<u32>(device.GetShaderStorageBufferAlignment()),
.support_geometry_shader_passthrough = device.HasGeometryShaderPassthrough(), .support_geometry_shader_passthrough = device.HasGeometryShaderPassthrough(),
.support_conditional_barrier = device.SupportsConditionalBarriers(), .support_conditional_barrier = device.SupportsConditionalBarriers(),
.support_ufloat_write_as_uint = true,
} { } {
if (use_asynchronous_shaders) { if (use_asynchronous_shaders) {
workers = CreateWorkers(); workers = CreateWorkers();

View File

@@ -78,8 +78,15 @@ vk::Buffer CreateBuffer(const Device& device, const MemoryAllocator& memory_allo
} }
} // Anonymous namespace } // Anonymous namespace
Buffer::Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params) Buffer::Buffer(BufferCacheRuntime& runtime, VideoCommon::NullBufferParams null_params)
: VideoCommon::BufferBase<VideoCore::RasterizerInterface>(null_params), tracker{4096} {} : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(null_params), tracker{4096} {
if (runtime.device.HasNullDescriptor()) {
return;
}
device = &runtime.device;
buffer = runtime.CreateNullBuffer();
is_null = true;
}
Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_, Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_,
VAddr cpu_addr_, u64 size_bytes_) VAddr cpu_addr_, u64 size_bytes_)
@@ -93,8 +100,12 @@ Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rast
VkBufferView Buffer::View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format) { VkBufferView Buffer::View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format) {
if (!device) { if (!device) {
// Null buffer, return a null descriptor // Null buffer supported, return a null descriptor
return VK_NULL_HANDLE; return VK_NULL_HANDLE;
} else if (is_null) {
// Null buffer not supported, adjust offset and size
offset = 0;
size = 0;
} }
const auto it{std::ranges::find_if(views, [offset, size, format](const BufferView& view) { const auto it{std::ranges::find_if(views, [offset, size, format](const BufferView& view) {
return offset == view.offset && size == view.size && format == view.format; return offset == view.offset && size == view.size && format == view.format;
@@ -563,22 +574,27 @@ void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bi
} }
buffer_handles.push_back(handle); buffer_handles.push_back(handle);
} }
const u32 device_max = device.GetMaxVertexInputBindings();
const u32 min_binding = std::min(bindings.min_index, device_max);
const u32 max_binding = std::min(bindings.max_index, device_max);
const u32 binding_count = max_binding - min_binding;
if (binding_count == 0) {
return;
}
if (device.IsExtExtendedDynamicStateSupported()) { if (device.IsExtExtendedDynamicStateSupported()) {
scheduler.Record([this, bindings_ = std::move(bindings), scheduler.Record([bindings_ = std::move(bindings),
buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) { buffer_handles_ = std::move(buffer_handles),
cmdbuf.BindVertexBuffers2EXT(bindings_.min_index, binding_count](vk::CommandBuffer cmdbuf) {
std::min(bindings_.max_index - bindings_.min_index, cmdbuf.BindVertexBuffers2EXT(bindings_.min_index, binding_count, buffer_handles_.data(),
device.GetMaxVertexInputBindings()), bindings_.offsets.data(), bindings_.sizes.data(),
buffer_handles_.data(), bindings_.offsets.data(), bindings_.strides.data());
bindings_.sizes.data(), bindings_.strides.data());
}); });
} else { } else {
scheduler.Record([this, bindings_ = std::move(bindings), scheduler.Record([bindings_ = std::move(bindings),
buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) { buffer_handles_ = std::move(buffer_handles),
cmdbuf.BindVertexBuffers(bindings_.min_index, binding_count](vk::CommandBuffer cmdbuf) {
std::min(bindings_.max_index - bindings_.min_index, cmdbuf.BindVertexBuffers(bindings_.min_index, binding_count, buffer_handles_.data(),
device.GetMaxVertexInputBindings()), bindings_.offsets.data());
buffer_handles_.data(), bindings_.offsets.data());
}); });
} }
} }
@@ -622,9 +638,12 @@ void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings<
} }
void BufferCacheRuntime::ReserveNullBuffer() { void BufferCacheRuntime::ReserveNullBuffer() {
if (null_buffer) { if (!null_buffer) {
return; null_buffer = CreateNullBuffer();
} }
}
vk::Buffer BufferCacheRuntime::CreateNullBuffer() {
VkBufferCreateInfo create_info{ VkBufferCreateInfo create_info{
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@@ -639,15 +658,17 @@ void BufferCacheRuntime::ReserveNullBuffer() {
if (device.IsExtTransformFeedbackSupported()) { if (device.IsExtTransformFeedbackSupported()) {
create_info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; create_info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
} }
null_buffer = memory_allocator.CreateBuffer(create_info, MemoryUsage::DeviceLocal); vk::Buffer ret = memory_allocator.CreateBuffer(create_info, MemoryUsage::DeviceLocal);
if (device.HasDebuggingToolAttached()) { if (device.HasDebuggingToolAttached()) {
null_buffer.SetObjectNameEXT("Null buffer"); ret.SetObjectNameEXT("Null buffer");
} }
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([buffer = *null_buffer](vk::CommandBuffer cmdbuf) { scheduler.Record([buffer = *ret](vk::CommandBuffer cmdbuf) {
cmdbuf.FillBuffer(buffer, 0, VK_WHOLE_SIZE, 0); cmdbuf.FillBuffer(buffer, 0, VK_WHOLE_SIZE, 0);
}); });
return ret;
} }
} // namespace Vulkan } // namespace Vulkan

View File

@@ -63,6 +63,7 @@ private:
vk::Buffer buffer; vk::Buffer buffer;
std::vector<BufferView> views; std::vector<BufferView> views;
VideoCommon::UsageTracker tracker; VideoCommon::UsageTracker tracker;
bool is_null{};
}; };
class QuadArrayIndexBuffer; class QuadArrayIndexBuffer;
@@ -151,6 +152,7 @@ private:
} }
void ReserveNullBuffer(); void ReserveNullBuffer();
vk::Buffer CreateNullBuffer();
const Device& device; const Device& device;
MemoryAllocator& memory_allocator; MemoryAllocator& memory_allocator;

View File

@@ -374,6 +374,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
.has_broken_robust = .has_broken_robust =
device.IsNvidia() && device.GetNvidiaArch() <= NvidiaArchitecture::Arch_Pascal, device.IsNvidia() && device.GetNvidiaArch() <= NvidiaArchitecture::Arch_Pascal,
.min_ssbo_alignment = device.GetStorageBufferAlignment(), .min_ssbo_alignment = device.GetStorageBufferAlignment(),
.max_user_clip_distances = device.GetMaxUserClipDistances(),
}; };
host_info = Shader::HostTranslateInfo{ host_info = Shader::HostTranslateInfo{
@@ -387,6 +388,9 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
.min_ssbo_alignment = static_cast<u32>(device.GetStorageBufferAlignment()), .min_ssbo_alignment = static_cast<u32>(device.GetStorageBufferAlignment()),
.support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(), .support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(),
.support_conditional_barrier = device.SupportsConditionalBarriers(), .support_conditional_barrier = device.SupportsConditionalBarriers(),
.support_ufloat_write_as_uint = driver_id != VK_DRIVER_ID_QUALCOMM_PROPRIETARY &&
driver_id != VK_DRIVER_ID_MESA_TURNIP &&
driver_id != VK_DRIVER_ID_ARM_PROPRIETARY,
}; };
if (device.GetMaxVertexInputAttributes() < Maxwell::NumVertexAttributes) { if (device.GetMaxVertexInputAttributes() < Maxwell::NumVertexAttributes) {

View File

@@ -289,12 +289,15 @@ public:
} }
if (has_multi_queries) { if (has_multi_queries) {
size_t intermediary_buffer_index = ObtainBuffer<false>(num_slots_used); const size_t min_accumulation_limit =
std::min(first_accumulation_checkpoint, num_slots_used);
const size_t max_accumulation_limit =
std::max(last_accumulation_checkpoint, num_slots_used);
const size_t intermediary_buffer_index = ObtainBuffer<false>(num_slots_used);
resolve_buffers.push_back(intermediary_buffer_index); resolve_buffers.push_back(intermediary_buffer_index);
queries_prefix_scan_pass->Run(*accumulation_buffer, *buffers[intermediary_buffer_index], queries_prefix_scan_pass->Run(*accumulation_buffer, *buffers[intermediary_buffer_index],
*buffers[resolve_buffer_index], num_slots_used, *buffers[resolve_buffer_index], num_slots_used,
std::min(first_accumulation_checkpoint, num_slots_used), min_accumulation_limit, max_accumulation_limit);
last_accumulation_checkpoint);
} else { } else {
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();

View File

@@ -76,6 +76,8 @@ static Shader::TexturePixelFormat ConvertTexturePixelFormat(const Tegra::Texture
return Shader::TexturePixelFormat::R16G16_SNORM; return Shader::TexturePixelFormat::R16G16_SNORM;
case VideoCore::Surface::PixelFormat::R16_SNORM: case VideoCore::Surface::PixelFormat::R16_SNORM:
return Shader::TexturePixelFormat::R16_SNORM; return Shader::TexturePixelFormat::R16_SNORM;
case VideoCore::Surface::PixelFormat::B10G11R11_FLOAT:
return Shader::TexturePixelFormat::B10G11R11_FLOAT;
default: default:
return Shader::TexturePixelFormat::OTHER; return Shader::TexturePixelFormat::OTHER;
} }

View File

@@ -695,6 +695,11 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
std::min(properties.properties.limits.maxVertexInputBindings, 16U); std::min(properties.properties.limits.maxVertexInputBindings, 16U);
} }
if (is_turnip) {
LOG_WARNING(Render_Vulkan, "Turnip requires higher-than-reported binding limits");
properties.properties.limits.maxVertexInputBindings = 32;
}
if (!extensions.extended_dynamic_state && extensions.extended_dynamic_state2) { if (!extensions.extended_dynamic_state && extensions.extended_dynamic_state2) {
LOG_INFO(Render_Vulkan, LOG_INFO(Render_Vulkan,
"Removing extendedDynamicState2 due to missing extendedDynamicState"); "Removing extendedDynamicState2 due to missing extendedDynamicState");

View File

@@ -665,6 +665,10 @@ public:
return properties.properties.limits.maxViewports; return properties.properties.limits.maxViewports;
} }
u32 GetMaxUserClipDistances() const {
return properties.properties.limits.maxClipDistances;
}
bool SupportsConditionalBarriers() const { bool SupportsConditionalBarriers() const {
return supports_conditional_barriers; return supports_conditional_barriers;
} }

View File

@@ -377,6 +377,8 @@ const char* ToString(VkResult result) noexcept {
return "VK_OPERATION_DEFERRED_KHR"; return "VK_OPERATION_DEFERRED_KHR";
case VkResult::VK_OPERATION_NOT_DEFERRED_KHR: case VkResult::VK_OPERATION_NOT_DEFERRED_KHR:
return "VK_OPERATION_NOT_DEFERRED_KHR"; return "VK_OPERATION_NOT_DEFERRED_KHR";
case VkResult::VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR:
return "VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR";
case VkResult::VK_PIPELINE_COMPILE_REQUIRED_EXT: case VkResult::VK_PIPELINE_COMPILE_REQUIRED_EXT:
return "VK_PIPELINE_COMPILE_REQUIRED_EXT"; return "VK_PIPELINE_COMPILE_REQUIRED_EXT";
case VkResult::VK_RESULT_MAX_ENUM: case VkResult::VK_RESULT_MAX_ENUM: