early-access version 4031
This commit is contained in:
parent
98941608ba
commit
40960d220b
15 changed files with 224 additions and 134 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 4030.
|
This is the source code for early-access 4031.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -196,42 +196,34 @@ Id Texture(EmitContext& ctx, IR::TextureInstInfo info, [[maybe_unused]] const IR
|
||||||
}
|
}
|
||||||
|
|
||||||
Id TextureImage(EmitContext& ctx, IR::TextureInstInfo info, const IR::Value& index) {
|
Id TextureImage(EmitContext& ctx, IR::TextureInstInfo info, const IR::Value& index) {
|
||||||
|
if (!index.IsImmediate() || index.U32() != 0) {
|
||||||
|
throw NotImplementedException("Indirect image indexing");
|
||||||
|
}
|
||||||
if (info.type == TextureType::Buffer) {
|
if (info.type == TextureType::Buffer) {
|
||||||
const TextureBufferDefinition& def{ctx.texture_buffers.at(info.descriptor_index)};
|
const TextureBufferDefinition& def{ctx.texture_buffers.at(info.descriptor_index)};
|
||||||
if (def.count > 1) {
|
if (def.count > 1) {
|
||||||
const Id buffer_pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))};
|
throw NotImplementedException("Indirect texture sample");
|
||||||
return ctx.OpLoad(ctx.image_buffer_type, buffer_pointer);
|
|
||||||
} else {
|
|
||||||
return ctx.OpLoad(ctx.image_buffer_type, def.id);
|
|
||||||
}
|
}
|
||||||
|
return ctx.OpLoad(ctx.image_buffer_type, def.id);
|
||||||
} else {
|
} else {
|
||||||
const TextureDefinition& def{ctx.textures.at(info.descriptor_index)};
|
const TextureDefinition& def{ctx.textures.at(info.descriptor_index)};
|
||||||
if (def.count > 1) {
|
if (def.count > 1) {
|
||||||
const Id texture_pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))};
|
throw NotImplementedException("Indirect texture sample");
|
||||||
return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, texture_pointer));
|
|
||||||
} else {
|
|
||||||
return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id));
|
|
||||||
}
|
}
|
||||||
|
return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Id Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) {
|
std::pair<Id, bool> Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) {
|
||||||
|
if (!index.IsImmediate() || index.U32() != 0) {
|
||||||
|
throw NotImplementedException("Indirect image indexing");
|
||||||
|
}
|
||||||
if (info.type == TextureType::Buffer) {
|
if (info.type == TextureType::Buffer) {
|
||||||
const ImageBufferDefinition def{ctx.image_buffers.at(info.descriptor_index)};
|
const ImageBufferDefinition def{ctx.image_buffers.at(info.descriptor_index)};
|
||||||
if (def.count > 1) {
|
return {ctx.OpLoad(def.image_type, def.id), def.is_integer};
|
||||||
const Id image_pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))};
|
|
||||||
return ctx.OpLoad(def.image_type, image_pointer);
|
|
||||||
} else {
|
|
||||||
return ctx.OpLoad(def.image_type, def.id);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const ImageDefinition def{ctx.images.at(info.descriptor_index)};
|
const ImageDefinition def{ctx.images.at(info.descriptor_index)};
|
||||||
if (def.count > 1) {
|
return {ctx.OpLoad(def.image_type, def.id), def.is_integer};
|
||||||
const Id image_pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))};
|
|
||||||
return ctx.OpLoad(def.image_type, image_pointer);
|
|
||||||
} else {
|
|
||||||
return ctx.OpLoad(def.image_type, def.id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,13 +566,23 @@ Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id co
|
||||||
LOG_WARNING(Shader_SPIRV, "Typeless image read not supported by host");
|
LOG_WARNING(Shader_SPIRV, "Typeless image read not supported by host");
|
||||||
return ctx.ConstantNull(ctx.U32[4]);
|
return ctx.ConstantNull(ctx.U32[4]);
|
||||||
}
|
}
|
||||||
return Emit(&EmitContext::OpImageSparseRead, &EmitContext::OpImageRead, ctx, inst, ctx.U32[4],
|
const auto [image, is_integer] = Image(ctx, index, info);
|
||||||
Image(ctx, index, info), coords, std::nullopt, std::span<const Id>{});
|
const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]};
|
||||||
|
Id color{Emit(&EmitContext::OpImageSparseRead, &EmitContext::OpImageRead, ctx, inst,
|
||||||
|
result_type, image, coords, std::nullopt, std::span<const Id>{})};
|
||||||
|
if (!is_integer) {
|
||||||
|
color = ctx.OpBitcast(ctx.U32[4], color);
|
||||||
|
}
|
||||||
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color) {
|
void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color) {
|
||||||
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
||||||
ctx.OpImageWrite(Image(ctx, index, info), coords, color);
|
const auto [image, is_integer] = Image(ctx, index, info);
|
||||||
|
if (!is_integer) {
|
||||||
|
color = ctx.OpBitcast(ctx.F32[4], color);
|
||||||
|
}
|
||||||
|
ctx.OpImageWrite(image, coords, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index) {
|
Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index) {
|
||||||
|
|
|
@ -7,22 +7,14 @@
|
||||||
|
|
||||||
namespace Shader::Backend::SPIRV {
|
namespace Shader::Backend::SPIRV {
|
||||||
namespace {
|
namespace {
|
||||||
Id ImagePointer(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) {
|
Id Image(EmitContext& ctx, IR::TextureInstInfo info) {
|
||||||
if (info.type == TextureType::Buffer) {
|
if (info.type == TextureType::Buffer) {
|
||||||
const ImageBufferDefinition def{ctx.image_buffers.at(info.descriptor_index)};
|
const ImageBufferDefinition def{ctx.image_buffers.at(info.descriptor_index)};
|
||||||
if (def.count > 1) {
|
|
||||||
return ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index));
|
|
||||||
} else {
|
|
||||||
return def.id;
|
return def.id;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const ImageDefinition def{ctx.images.at(info.descriptor_index)};
|
const ImageDefinition def{ctx.images.at(info.descriptor_index)};
|
||||||
if (def.count > 1) {
|
|
||||||
return ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index));
|
|
||||||
} else {
|
|
||||||
return def.id;
|
return def.id;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Id, Id> AtomicArgs(EmitContext& ctx) {
|
std::pair<Id, Id> AtomicArgs(EmitContext& ctx) {
|
||||||
|
@ -33,12 +25,15 @@ std::pair<Id, Id> AtomicArgs(EmitContext& ctx) {
|
||||||
|
|
||||||
Id ImageAtomicU32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id value,
|
Id ImageAtomicU32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id value,
|
||||||
Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id)) {
|
Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id)) {
|
||||||
|
if (!index.IsImmediate() || index.U32() != 0) {
|
||||||
|
// TODO: handle layers
|
||||||
|
throw NotImplementedException("Image indexing");
|
||||||
|
}
|
||||||
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
||||||
const Id image_pointer{ImagePointer(ctx, index, info)};
|
const Id image{Image(ctx, info)};
|
||||||
const Id texel_pointer{
|
const Id pointer{ctx.OpImageTexelPointer(ctx.image_u32, image, coords, ctx.Const(0U))};
|
||||||
ctx.OpImageTexelPointer(ctx.image_u32, image_pointer, coords, ctx.Const(0U))};
|
|
||||||
const auto [scope, semantics]{AtomicArgs(ctx)};
|
const auto [scope, semantics]{AtomicArgs(ctx)};
|
||||||
return (ctx.*atomic_func)(ctx.U32[1], texel_pointer, scope, semantics, value);
|
return (ctx.*atomic_func)(ctx.U32[1], pointer, scope, semantics, value);
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
|
|
@ -74,28 +74,19 @@ spv::ImageFormat GetImageFormat(ImageFormat format) {
|
||||||
throw InvalidArgument("Invalid image format {}", format);
|
throw InvalidArgument("Invalid image format {}", format);
|
||||||
}
|
}
|
||||||
|
|
||||||
Id GetImageSampledType(EmitContext& ctx, const ImageDescriptor& desc) {
|
Id ImageType(EmitContext& ctx, const ImageDescriptor& desc, Id sampled_type) {
|
||||||
if (desc.is_float) {
|
|
||||||
return ctx.F32[1];
|
|
||||||
} else {
|
|
||||||
return ctx.U32[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Id ImageType(EmitContext& ctx, const ImageDescriptor& desc) {
|
|
||||||
const spv::ImageFormat format{GetImageFormat(desc.format)};
|
const spv::ImageFormat format{GetImageFormat(desc.format)};
|
||||||
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(sampled_type, spv::Dim::Dim1D, false, false, false, 2, format);
|
||||||
case TextureType::ColorArray1D:
|
case TextureType::ColorArray1D:
|
||||||
return ctx.TypeImage(type, spv::Dim::Dim1D, false, true, false, 2, format);
|
return ctx.TypeImage(sampled_type, spv::Dim::Dim1D, false, true, false, 2, format);
|
||||||
case TextureType::Color2D:
|
case TextureType::Color2D:
|
||||||
return ctx.TypeImage(type, spv::Dim::Dim2D, false, false, false, 2, format);
|
return ctx.TypeImage(sampled_type, spv::Dim::Dim2D, false, false, false, 2, format);
|
||||||
case TextureType::ColorArray2D:
|
case TextureType::ColorArray2D:
|
||||||
return ctx.TypeImage(type, spv::Dim::Dim2D, false, true, false, 2, format);
|
return ctx.TypeImage(sampled_type, spv::Dim::Dim2D, false, true, false, 2, format);
|
||||||
case TextureType::Color3D:
|
case TextureType::Color3D:
|
||||||
return ctx.TypeImage(type, spv::Dim::Dim3D, false, false, false, 2, format);
|
return ctx.TypeImage(sampled_type, spv::Dim::Dim3D, false, false, false, 2, format);
|
||||||
case TextureType::Buffer:
|
case TextureType::Buffer:
|
||||||
throw NotImplementedException("Image buffer");
|
throw NotImplementedException("Image buffer");
|
||||||
default:
|
default:
|
||||||
|
@ -1253,20 +1244,18 @@ void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) {
|
||||||
const spv::ImageFormat format{spv::ImageFormat::Unknown};
|
const spv::ImageFormat format{spv::ImageFormat::Unknown};
|
||||||
image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format);
|
image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format);
|
||||||
|
|
||||||
const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_buffer_type)};
|
const Id type{TypePointer(spv::StorageClass::UniformConstant, image_buffer_type)};
|
||||||
texture_buffers.reserve(info.texture_buffer_descriptors.size());
|
texture_buffers.reserve(info.texture_buffer_descriptors.size());
|
||||||
for (const TextureBufferDescriptor& desc : info.texture_buffer_descriptors) {
|
for (const TextureBufferDescriptor& desc : info.texture_buffer_descriptors) {
|
||||||
if (desc.count != 1) {
|
if (desc.count != 1) {
|
||||||
LOG_WARNING(Shader_SPIRV, "Array of texture buffers");
|
throw NotImplementedException("Array of texture buffers");
|
||||||
}
|
}
|
||||||
const Id desc_type{DescType(*this, image_buffer_type, pointer_type, desc.count)};
|
const Id id{AddGlobalVariable(type, spv::StorageClass::UniformConstant)};
|
||||||
const Id id{AddGlobalVariable(desc_type, spv::StorageClass::UniformConstant)};
|
|
||||||
Decorate(id, spv::Decoration::Binding, binding);
|
Decorate(id, spv::Decoration::Binding, binding);
|
||||||
Decorate(id, spv::Decoration::DescriptorSet, 0U);
|
Decorate(id, spv::Decoration::DescriptorSet, 0U);
|
||||||
Name(id, NameOf(stage, desc, "texbuf"));
|
Name(id, NameOf(stage, desc, "texbuf"));
|
||||||
texture_buffers.push_back({
|
texture_buffers.push_back({
|
||||||
.id = id,
|
.id = id,
|
||||||
.pointer_type = pointer_type,
|
|
||||||
.count = desc.count,
|
.count = desc.count,
|
||||||
});
|
});
|
||||||
if (profile.supported_spirv >= 0x00010400) {
|
if (profile.supported_spirv >= 0x00010400) {
|
||||||
|
@ -1280,10 +1269,12 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) {
|
||||||
image_buffers.reserve(info.image_buffer_descriptors.size());
|
image_buffers.reserve(info.image_buffer_descriptors.size());
|
||||||
for (const ImageBufferDescriptor& desc : info.image_buffer_descriptors) {
|
for (const ImageBufferDescriptor& desc : info.image_buffer_descriptors) {
|
||||||
if (desc.count != 1) {
|
if (desc.count != 1) {
|
||||||
LOG_WARNING(Shader_SPIRV, "Array of image buffers");
|
throw NotImplementedException("Array of image buffers");
|
||||||
}
|
}
|
||||||
const spv::ImageFormat format{GetImageFormat(desc.format)};
|
const spv::ImageFormat format{GetImageFormat(desc.format)};
|
||||||
const Id image_type{TypeImage(U32[1], spv::Dim::Buffer, false, false, false, 2, format)};
|
const Id sampled_type{desc.is_integer ? U32[1] : F32[1]};
|
||||||
|
const Id image_type{
|
||||||
|
TypeImage(sampled_type, spv::Dim::Buffer, false, false, false, 2, format)};
|
||||||
const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
|
const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
|
||||||
const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
|
const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
|
||||||
Decorate(id, spv::Decoration::Binding, binding);
|
Decorate(id, spv::Decoration::Binding, binding);
|
||||||
|
@ -1292,8 +1283,8 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) {
|
||||||
image_buffers.push_back({
|
image_buffers.push_back({
|
||||||
.id = id,
|
.id = id,
|
||||||
.image_type = image_type,
|
.image_type = image_type,
|
||||||
.pointer_type = pointer_type,
|
|
||||||
.count = desc.count,
|
.count = desc.count,
|
||||||
|
.is_integer = desc.is_integer,
|
||||||
});
|
});
|
||||||
if (profile.supported_spirv >= 0x00010400) {
|
if (profile.supported_spirv >= 0x00010400) {
|
||||||
interfaces.push_back(id);
|
interfaces.push_back(id);
|
||||||
|
@ -1336,20 +1327,20 @@ void EmitContext::DefineImages(const Info& info, u32& binding, u32& scaling_inde
|
||||||
images.reserve(info.image_descriptors.size());
|
images.reserve(info.image_descriptors.size());
|
||||||
for (const ImageDescriptor& desc : info.image_descriptors) {
|
for (const ImageDescriptor& desc : info.image_descriptors) {
|
||||||
if (desc.count != 1) {
|
if (desc.count != 1) {
|
||||||
LOG_WARNING(Shader_SPIRV, "Array of images");
|
throw NotImplementedException("Array of images");
|
||||||
}
|
}
|
||||||
const Id image_type{ImageType(*this, desc)};
|
const Id sampled_type{desc.is_integer ? U32[1] : F32[1]};
|
||||||
|
const Id image_type{ImageType(*this, desc, sampled_type)};
|
||||||
const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
|
const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
|
||||||
const Id desc_type{DescType(*this, image_type, pointer_type, desc.count)};
|
const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
|
||||||
const Id id{AddGlobalVariable(desc_type, spv::StorageClass::UniformConstant)};
|
|
||||||
Decorate(id, spv::Decoration::Binding, binding);
|
Decorate(id, spv::Decoration::Binding, binding);
|
||||||
Decorate(id, spv::Decoration::DescriptorSet, 0U);
|
Decorate(id, spv::Decoration::DescriptorSet, 0U);
|
||||||
Name(id, NameOf(stage, desc, "img"));
|
Name(id, NameOf(stage, desc, "img"));
|
||||||
images.push_back({
|
images.push_back({
|
||||||
.id = id,
|
.id = id,
|
||||||
.image_type = image_type,
|
.image_type = image_type,
|
||||||
.pointer_type = pointer_type,
|
|
||||||
.count = desc.count,
|
.count = desc.count,
|
||||||
|
.is_integer = desc.is_integer,
|
||||||
});
|
});
|
||||||
if (profile.supported_spirv >= 0x00010400) {
|
if (profile.supported_spirv >= 0x00010400) {
|
||||||
interfaces.push_back(id);
|
interfaces.push_back(id);
|
||||||
|
|
|
@ -40,22 +40,21 @@ struct TextureDefinition {
|
||||||
|
|
||||||
struct TextureBufferDefinition {
|
struct TextureBufferDefinition {
|
||||||
Id id;
|
Id id;
|
||||||
Id pointer_type;
|
|
||||||
u32 count;
|
u32 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImageBufferDefinition {
|
struct ImageBufferDefinition {
|
||||||
Id id;
|
Id id;
|
||||||
Id image_type;
|
Id image_type;
|
||||||
Id pointer_type;
|
|
||||||
u32 count;
|
u32 count;
|
||||||
|
bool is_integer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImageDefinition {
|
struct ImageDefinition {
|
||||||
Id id;
|
Id id;
|
||||||
Id image_type;
|
Id image_type;
|
||||||
Id pointer_type;
|
|
||||||
u32 count;
|
u32 count;
|
||||||
|
bool is_integer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UniformDefinitions {
|
struct UniformDefinitions {
|
||||||
|
|
|
@ -24,6 +24,8 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] virtual TexturePixelFormat ReadTexturePixelFormat(u32 raw_handle) = 0;
|
[[nodiscard]] virtual TexturePixelFormat ReadTexturePixelFormat(u32 raw_handle) = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual bool IsTexturePixelFormatInteger(u32 raw_handle) = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual u32 ReadViewportTransformState() = 0;
|
[[nodiscard]] virtual u32 ReadViewportTransformState() = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual u32 TextureBoundBuffer() const = 0;
|
[[nodiscard]] virtual u32 TextureBoundBuffer() const = 0;
|
||||||
|
|
|
@ -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, Opaque, )
|
OPCODE(ImageWrite, Void, Opaque, Opaque, U32x4, )
|
||||||
|
|
||||||
OPCODE(IsTextureScaled, U1, U32, )
|
OPCODE(IsTextureScaled, U1, U32, )
|
||||||
OPCODE(IsImageScaled, U1, U32, )
|
OPCODE(IsImageScaled, U1, U32, )
|
||||||
|
|
|
@ -21,8 +21,6 @@ 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
|
||||||
|
|
|
@ -815,6 +815,15 @@ bool FindGradient3DDerivatives(std::array<IR::Value, 3>& results, IR::Value coor
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConvertDerivatives(std::array<IR::Value, 3>& results, IR::IREmitter& ir) {
|
||||||
|
for (size_t i = 0; i < 3; i++) {
|
||||||
|
if (results[i].Type() == IR::Type::U32) {
|
||||||
|
results[i] = results[i].IsImmediate() ? ir.Imm32(Common::BitCast<f32>(results[i].U32()))
|
||||||
|
: ir.BitCast<IR::F32>(IR::U32(results[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FoldImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) {
|
void FoldImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) {
|
||||||
IR::TextureInstInfo info = inst.Flags<IR::TextureInstInfo>();
|
IR::TextureInstInfo info = inst.Flags<IR::TextureInstInfo>();
|
||||||
auto orig_opcode = inst.GetOpcode();
|
auto orig_opcode = inst.GetOpcode();
|
||||||
|
@ -831,12 +840,14 @@ void FoldImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) {
|
||||||
if (!offset.IsImmediate()) {
|
if (!offset.IsImmediate()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
|
||||||
IR::Inst* const inst2 = coords.InstRecursive();
|
IR::Inst* const inst2 = coords.InstRecursive();
|
||||||
std::array<std::array<IR::Value, 3>, 3> results_matrix;
|
std::array<std::array<IR::Value, 3>, 3> results_matrix;
|
||||||
for (size_t i = 0; i < 3; i++) {
|
for (size_t i = 0; i < 3; i++) {
|
||||||
if (!FindGradient3DDerivatives(results_matrix[i], inst2->Arg(i).Resolve())) {
|
if (!FindGradient3DDerivatives(results_matrix[i], inst2->Arg(i).Resolve())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ConvertDerivatives(results_matrix[i], ir);
|
||||||
}
|
}
|
||||||
IR::F32 lod_clamp{};
|
IR::F32 lod_clamp{};
|
||||||
if (info.has_lod_clamp != 0) {
|
if (info.has_lod_clamp != 0) {
|
||||||
|
@ -846,7 +857,6 @@ void FoldImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) {
|
||||||
lod_clamp = IR::F32{bias_lc};
|
lod_clamp = IR::F32{bias_lc};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
|
|
||||||
IR::Value new_coords =
|
IR::Value new_coords =
|
||||||
ir.CompositeConstruct(results_matrix[0][0], results_matrix[1][0], results_matrix[2][0]);
|
ir.CompositeConstruct(results_matrix[0][0], results_matrix[1][0], results_matrix[2][0]);
|
||||||
IR::Value derivatives_1 = ir.CompositeConstruct(results_matrix[0][1], results_matrix[0][2],
|
IR::Value derivatives_1 = ir.CompositeConstruct(results_matrix[0][1], results_matrix[0][2],
|
||||||
|
|
|
@ -372,8 +372,8 @@ 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) {
|
bool IsTexturePixelFormatInteger(Environment& env, const ConstBufferAddr& cbuf) {
|
||||||
return ReadTexturePixelFormat(env, cbuf) == TexturePixelFormat::B10G11R11_FLOAT;
|
return env.IsTexturePixelFormatInteger(GetTextureHandle(env, cbuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
class Descriptors {
|
class Descriptors {
|
||||||
|
@ -407,6 +407,7 @@ public:
|
||||||
})};
|
})};
|
||||||
image_buffer_descriptors[index].is_written |= desc.is_written;
|
image_buffer_descriptors[index].is_written |= desc.is_written;
|
||||||
image_buffer_descriptors[index].is_read |= desc.is_read;
|
image_buffer_descriptors[index].is_read |= desc.is_read;
|
||||||
|
image_buffer_descriptors[index].is_integer |= desc.is_integer;
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,11 +433,11 @@ 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.is_float == existing.is_float;
|
desc.size_shift == existing.size_shift;
|
||||||
})};
|
})};
|
||||||
// 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;
|
||||||
|
image_descriptors[index].is_integer |= desc.is_integer;
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,6 +475,20 @@ void PatchImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) {
|
||||||
ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 1))))));
|
ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 1))))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsPixelFormatSNorm(TexturePixelFormat pixel_format) {
|
||||||
|
switch (pixel_format) {
|
||||||
|
case TexturePixelFormat::A8B8G8R8_SNORM:
|
||||||
|
case TexturePixelFormat::R8G8_SNORM:
|
||||||
|
case TexturePixelFormat::R8_SNORM:
|
||||||
|
case TexturePixelFormat::R16G16B16A16_SNORM:
|
||||||
|
case TexturePixelFormat::R16G16_SNORM:
|
||||||
|
case TexturePixelFormat::R16_SNORM:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PatchTexelFetch(IR::Block& block, IR::Inst& inst, TexturePixelFormat pixel_format) {
|
void PatchTexelFetch(IR::Block& block, IR::Inst& inst, TexturePixelFormat pixel_format) {
|
||||||
const auto it{IR::Block::InstructionList::s_iterator_to(inst)};
|
const auto it{IR::Block::InstructionList::s_iterator_to(inst)};
|
||||||
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
|
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
|
||||||
|
@ -505,19 +520,6 @@ 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) {
|
||||||
|
@ -549,9 +551,6 @@ 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()) {
|
||||||
|
@ -608,11 +607,13 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
|
||||||
}
|
}
|
||||||
const bool is_written{inst->GetOpcode() != IR::Opcode::ImageRead};
|
const bool is_written{inst->GetOpcode() != IR::Opcode::ImageRead};
|
||||||
const bool is_read{inst->GetOpcode() != IR::Opcode::ImageWrite};
|
const bool is_read{inst->GetOpcode() != IR::Opcode::ImageWrite};
|
||||||
|
const bool is_integer{IsTexturePixelFormatInteger(env, cbuf)};
|
||||||
if (flags.type == TextureType::Buffer) {
|
if (flags.type == TextureType::Buffer) {
|
||||||
index = descriptors.Add(ImageBufferDescriptor{
|
index = descriptors.Add(ImageBufferDescriptor{
|
||||||
.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_integer = is_integer,
|
||||||
.cbuf_index = cbuf.index,
|
.cbuf_index = cbuf.index,
|
||||||
.cbuf_offset = cbuf.offset,
|
.cbuf_offset = cbuf.offset,
|
||||||
.count = cbuf.count,
|
.count = cbuf.count,
|
||||||
|
@ -624,7 +625,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,
|
.is_integer = is_integer,
|
||||||
.cbuf_index = cbuf.index,
|
.cbuf_index = cbuf.index,
|
||||||
.cbuf_offset = cbuf.offset,
|
.cbuf_offset = cbuf.offset,
|
||||||
.count = cbuf.count,
|
.count = cbuf.count,
|
||||||
|
@ -680,14 +681,10 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
|
||||||
if (!host_info.support_snorm_render_buffer && inst->GetOpcode() == IR::Opcode::ImageFetch &&
|
if (!host_info.support_snorm_render_buffer && inst->GetOpcode() == IR::Opcode::ImageFetch &&
|
||||||
flags.type == TextureType::Buffer) {
|
flags.type == TextureType::Buffer) {
|
||||||
const auto pixel_format = ReadTexturePixelFormat(env, cbuf);
|
const auto pixel_format = ReadTexturePixelFormat(env, cbuf);
|
||||||
if (pixel_format != TexturePixelFormat::OTHER) {
|
if (IsPixelFormatSNorm(pixel_format)) {
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,15 +35,109 @@ enum class TextureType : u32 {
|
||||||
};
|
};
|
||||||
constexpr u32 NUM_TEXTURE_TYPES = 9;
|
constexpr u32 NUM_TEXTURE_TYPES = 9;
|
||||||
|
|
||||||
enum class TexturePixelFormat : u32 {
|
enum class TexturePixelFormat {
|
||||||
|
A8B8G8R8_UNORM,
|
||||||
A8B8G8R8_SNORM,
|
A8B8G8R8_SNORM,
|
||||||
|
A8B8G8R8_SINT,
|
||||||
|
A8B8G8R8_UINT,
|
||||||
|
R5G6B5_UNORM,
|
||||||
|
B5G6R5_UNORM,
|
||||||
|
A1R5G5B5_UNORM,
|
||||||
|
A2B10G10R10_UNORM,
|
||||||
|
A2B10G10R10_UINT,
|
||||||
|
A2R10G10B10_UNORM,
|
||||||
|
A1B5G5R5_UNORM,
|
||||||
|
A5B5G5R1_UNORM,
|
||||||
|
R8_UNORM,
|
||||||
R8_SNORM,
|
R8_SNORM,
|
||||||
R8G8_SNORM,
|
R8_SINT,
|
||||||
|
R8_UINT,
|
||||||
|
R16G16B16A16_FLOAT,
|
||||||
|
R16G16B16A16_UNORM,
|
||||||
R16G16B16A16_SNORM,
|
R16G16B16A16_SNORM,
|
||||||
R16G16_SNORM,
|
R16G16B16A16_SINT,
|
||||||
R16_SNORM,
|
R16G16B16A16_UINT,
|
||||||
B10G11R11_FLOAT,
|
B10G11R11_FLOAT,
|
||||||
OTHER
|
R32G32B32A32_UINT,
|
||||||
|
BC1_RGBA_UNORM,
|
||||||
|
BC2_UNORM,
|
||||||
|
BC3_UNORM,
|
||||||
|
BC4_UNORM,
|
||||||
|
BC4_SNORM,
|
||||||
|
BC5_UNORM,
|
||||||
|
BC5_SNORM,
|
||||||
|
BC7_UNORM,
|
||||||
|
BC6H_UFLOAT,
|
||||||
|
BC6H_SFLOAT,
|
||||||
|
ASTC_2D_4X4_UNORM,
|
||||||
|
B8G8R8A8_UNORM,
|
||||||
|
R32G32B32A32_FLOAT,
|
||||||
|
R32G32B32A32_SINT,
|
||||||
|
R32G32_FLOAT,
|
||||||
|
R32G32_SINT,
|
||||||
|
R32_FLOAT,
|
||||||
|
R16_FLOAT,
|
||||||
|
R16_UNORM,
|
||||||
|
R16_SNORM,
|
||||||
|
R16_UINT,
|
||||||
|
R16_SINT,
|
||||||
|
R16G16_UNORM,
|
||||||
|
R16G16_FLOAT,
|
||||||
|
R16G16_UINT,
|
||||||
|
R16G16_SINT,
|
||||||
|
R16G16_SNORM,
|
||||||
|
R32G32B32_FLOAT,
|
||||||
|
A8B8G8R8_SRGB,
|
||||||
|
R8G8_UNORM,
|
||||||
|
R8G8_SNORM,
|
||||||
|
R8G8_SINT,
|
||||||
|
R8G8_UINT,
|
||||||
|
R32G32_UINT,
|
||||||
|
R16G16B16X16_FLOAT,
|
||||||
|
R32_UINT,
|
||||||
|
R32_SINT,
|
||||||
|
ASTC_2D_8X8_UNORM,
|
||||||
|
ASTC_2D_8X5_UNORM,
|
||||||
|
ASTC_2D_5X4_UNORM,
|
||||||
|
B8G8R8A8_SRGB,
|
||||||
|
BC1_RGBA_SRGB,
|
||||||
|
BC2_SRGB,
|
||||||
|
BC3_SRGB,
|
||||||
|
BC7_SRGB,
|
||||||
|
A4B4G4R4_UNORM,
|
||||||
|
G4R4_UNORM,
|
||||||
|
ASTC_2D_4X4_SRGB,
|
||||||
|
ASTC_2D_8X8_SRGB,
|
||||||
|
ASTC_2D_8X5_SRGB,
|
||||||
|
ASTC_2D_5X4_SRGB,
|
||||||
|
ASTC_2D_5X5_UNORM,
|
||||||
|
ASTC_2D_5X5_SRGB,
|
||||||
|
ASTC_2D_10X8_UNORM,
|
||||||
|
ASTC_2D_10X8_SRGB,
|
||||||
|
ASTC_2D_6X6_UNORM,
|
||||||
|
ASTC_2D_6X6_SRGB,
|
||||||
|
ASTC_2D_10X6_UNORM,
|
||||||
|
ASTC_2D_10X6_SRGB,
|
||||||
|
ASTC_2D_10X5_UNORM,
|
||||||
|
ASTC_2D_10X5_SRGB,
|
||||||
|
ASTC_2D_10X10_UNORM,
|
||||||
|
ASTC_2D_10X10_SRGB,
|
||||||
|
ASTC_2D_12X10_UNORM,
|
||||||
|
ASTC_2D_12X10_SRGB,
|
||||||
|
ASTC_2D_12X12_UNORM,
|
||||||
|
ASTC_2D_12X12_SRGB,
|
||||||
|
ASTC_2D_8X6_UNORM,
|
||||||
|
ASTC_2D_8X6_SRGB,
|
||||||
|
ASTC_2D_6X5_UNORM,
|
||||||
|
ASTC_2D_6X5_SRGB,
|
||||||
|
E5B9G9R9_FLOAT,
|
||||||
|
D32_FLOAT,
|
||||||
|
D16_UNORM,
|
||||||
|
X8_D24_UNORM,
|
||||||
|
S8_UINT,
|
||||||
|
D24_UNORM_S8_UINT,
|
||||||
|
S8_UINT_D24_UNORM,
|
||||||
|
D32_FLOAT_S8_UINT,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ImageFormat : u32 {
|
enum class ImageFormat : u32 {
|
||||||
|
@ -98,6 +192,7 @@ struct ImageBufferDescriptor {
|
||||||
ImageFormat format;
|
ImageFormat format;
|
||||||
bool is_written;
|
bool is_written;
|
||||||
bool is_read;
|
bool is_read;
|
||||||
|
bool is_integer;
|
||||||
u32 cbuf_index;
|
u32 cbuf_index;
|
||||||
u32 cbuf_offset;
|
u32 cbuf_offset;
|
||||||
u32 count;
|
u32 count;
|
||||||
|
@ -130,7 +225,7 @@ struct ImageDescriptor {
|
||||||
ImageFormat format;
|
ImageFormat format;
|
||||||
bool is_written;
|
bool is_written;
|
||||||
bool is_read;
|
bool is_read;
|
||||||
bool is_float;
|
bool is_integer;
|
||||||
u32 cbuf_index;
|
u32 cbuf_index;
|
||||||
u32 cbuf_offset;
|
u32 cbuf_offset;
|
||||||
u32 count;
|
u32 count;
|
||||||
|
|
|
@ -51,7 +51,7 @@ using VideoCommon::LoadPipelines;
|
||||||
using VideoCommon::SerializePipeline;
|
using VideoCommon::SerializePipeline;
|
||||||
using Context = ShaderContext::Context;
|
using Context = ShaderContext::Context;
|
||||||
|
|
||||||
constexpr u32 CACHE_VERSION = 9;
|
constexpr u32 CACHE_VERSION = 10;
|
||||||
|
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
auto MakeSpan(Container& container) {
|
auto MakeSpan(Container& container) {
|
||||||
|
@ -245,7 +245,6 @@ 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();
|
||||||
|
|
|
@ -54,7 +54,7 @@ using VideoCommon::FileEnvironment;
|
||||||
using VideoCommon::GenericEnvironment;
|
using VideoCommon::GenericEnvironment;
|
||||||
using VideoCommon::GraphicsEnvironment;
|
using VideoCommon::GraphicsEnvironment;
|
||||||
|
|
||||||
constexpr u32 CACHE_VERSION = 10;
|
constexpr u32 CACHE_VERSION = 11;
|
||||||
constexpr std::array<char, 8> VULKAN_CACHE_MAGIC_NUMBER{'y', 'u', 'z', 'u', 'v', 'k', 'c', 'h'};
|
constexpr std::array<char, 8> VULKAN_CACHE_MAGIC_NUMBER{'y', 'u', 'z', 'u', 'v', 'k', 'c', 'h'};
|
||||||
|
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
|
@ -388,9 +388,6 @@ 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) {
|
||||||
|
|
|
@ -62,25 +62,9 @@ static Shader::TextureType ConvertTextureType(const Tegra::Texture::TICEntry& en
|
||||||
}
|
}
|
||||||
|
|
||||||
static Shader::TexturePixelFormat ConvertTexturePixelFormat(const Tegra::Texture::TICEntry& entry) {
|
static Shader::TexturePixelFormat ConvertTexturePixelFormat(const Tegra::Texture::TICEntry& entry) {
|
||||||
switch (PixelFormatFromTextureInfo(entry.format, entry.r_type, entry.g_type, entry.b_type,
|
return static_cast<Shader::TexturePixelFormat>(
|
||||||
entry.a_type, entry.srgb_conversion)) {
|
PixelFormatFromTextureInfo(entry.format, entry.r_type, entry.g_type, entry.b_type,
|
||||||
case VideoCore::Surface::PixelFormat::A8B8G8R8_SNORM:
|
entry.a_type, entry.srgb_conversion));
|
||||||
return Shader::TexturePixelFormat::A8B8G8R8_SNORM;
|
|
||||||
case VideoCore::Surface::PixelFormat::R8_SNORM:
|
|
||||||
return Shader::TexturePixelFormat::R8_SNORM;
|
|
||||||
case VideoCore::Surface::PixelFormat::R8G8_SNORM:
|
|
||||||
return Shader::TexturePixelFormat::R8G8_SNORM;
|
|
||||||
case VideoCore::Surface::PixelFormat::R16G16B16A16_SNORM:
|
|
||||||
return Shader::TexturePixelFormat::R16G16B16A16_SNORM;
|
|
||||||
case VideoCore::Surface::PixelFormat::R16G16_SNORM:
|
|
||||||
return Shader::TexturePixelFormat::R16G16_SNORM;
|
|
||||||
case VideoCore::Surface::PixelFormat::R16_SNORM:
|
|
||||||
return Shader::TexturePixelFormat::R16_SNORM;
|
|
||||||
case VideoCore::Surface::PixelFormat::B10G11R11_FLOAT:
|
|
||||||
return Shader::TexturePixelFormat::B10G11R11_FLOAT;
|
|
||||||
default:
|
|
||||||
return Shader::TexturePixelFormat::OTHER;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string_view StageToPrefix(Shader::Stage stage) {
|
static std::string_view StageToPrefix(Shader::Stage stage) {
|
||||||
|
@ -400,6 +384,11 @@ Shader::TexturePixelFormat GraphicsEnvironment::ReadTexturePixelFormat(u32 handl
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GraphicsEnvironment::IsTexturePixelFormatInteger(u32 handle) {
|
||||||
|
return VideoCore::Surface::IsPixelFormatInteger(
|
||||||
|
static_cast<VideoCore::Surface::PixelFormat>(ReadTexturePixelFormat(handle)));
|
||||||
|
}
|
||||||
|
|
||||||
u32 GraphicsEnvironment::ReadViewportTransformState() {
|
u32 GraphicsEnvironment::ReadViewportTransformState() {
|
||||||
const auto& regs{maxwell3d->regs};
|
const auto& regs{maxwell3d->regs};
|
||||||
viewport_transform_state = regs.viewport_scale_offset_enabled;
|
viewport_transform_state = regs.viewport_scale_offset_enabled;
|
||||||
|
@ -450,6 +439,11 @@ Shader::TexturePixelFormat ComputeEnvironment::ReadTexturePixelFormat(u32 handle
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ComputeEnvironment::IsTexturePixelFormatInteger(u32 handle) {
|
||||||
|
return VideoCore::Surface::IsPixelFormatInteger(
|
||||||
|
static_cast<VideoCore::Surface::PixelFormat>(ReadTexturePixelFormat(handle)));
|
||||||
|
}
|
||||||
|
|
||||||
u32 ComputeEnvironment::ReadViewportTransformState() {
|
u32 ComputeEnvironment::ReadViewportTransformState() {
|
||||||
return viewport_transform_state;
|
return viewport_transform_state;
|
||||||
}
|
}
|
||||||
|
@ -553,6 +547,11 @@ Shader::TexturePixelFormat FileEnvironment::ReadTexturePixelFormat(u32 handle) {
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FileEnvironment::IsTexturePixelFormatInteger(u32 handle) {
|
||||||
|
return VideoCore::Surface::IsPixelFormatInteger(
|
||||||
|
static_cast<VideoCore::Surface::PixelFormat>(ReadTexturePixelFormat(handle)));
|
||||||
|
}
|
||||||
|
|
||||||
u32 FileEnvironment::ReadViewportTransformState() {
|
u32 FileEnvironment::ReadViewportTransformState() {
|
||||||
return viewport_transform_state;
|
return viewport_transform_state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,8 @@ public:
|
||||||
|
|
||||||
Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override;
|
Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override;
|
||||||
|
|
||||||
|
bool IsTexturePixelFormatInteger(u32 handle) override;
|
||||||
|
|
||||||
u32 ReadViewportTransformState() override;
|
u32 ReadViewportTransformState() override;
|
||||||
|
|
||||||
std::optional<Shader::ReplaceConstant> GetReplaceConstBuffer(u32 bank, u32 offset) override;
|
std::optional<Shader::ReplaceConstant> GetReplaceConstBuffer(u32 bank, u32 offset) override;
|
||||||
|
@ -139,6 +141,8 @@ public:
|
||||||
|
|
||||||
Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override;
|
Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override;
|
||||||
|
|
||||||
|
bool IsTexturePixelFormatInteger(u32 handle) override;
|
||||||
|
|
||||||
u32 ReadViewportTransformState() override;
|
u32 ReadViewportTransformState() override;
|
||||||
|
|
||||||
std::optional<Shader::ReplaceConstant> GetReplaceConstBuffer(
|
std::optional<Shader::ReplaceConstant> GetReplaceConstBuffer(
|
||||||
|
@ -171,6 +175,8 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override;
|
[[nodiscard]] Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override;
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsTexturePixelFormatInteger(u32 handle) override;
|
||||||
|
|
||||||
[[nodiscard]] u32 ReadViewportTransformState() override;
|
[[nodiscard]] u32 ReadViewportTransformState() override;
|
||||||
|
|
||||||
[[nodiscard]] u32 LocalMemorySize() const override;
|
[[nodiscard]] u32 LocalMemorySize() const override;
|
||||||
|
|
Loading…
Reference in a new issue