mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-10-20 18:59:26 +02:00
[shader_recompiler] Implement indirect image/texture array indexing (#3608)
Fixes missing textures in Luigi's Mansion 3 (Invisible Mice lol) and potentially other titles by implementing OpAccessChain indexing into descriptor arrays instead of throwing NotImplementedException. Co-authored-by: JPikachu <fakemail@gmail.com> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3608 Reviewed-by: MaranBr <maranbr@eden-emu.dev> Reviewed-by: DraVee <dravee@eden-emu.dev> Reviewed-by: CamilleLaVey <camillelavey99@gmail.com> Co-authored-by: JPikachu <jpikachu@eden-emu.dev> Co-committed-by: JPikachu <jpikachu@eden-emu.dev>
This commit is contained in:
parent
213f7b810d
commit
f77c91431f
3 changed files with 20 additions and 14 deletions
|
|
@ -197,33 +197,41 @@ 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) {
|
||||||
throw NotImplementedException("Indirect texture sample");
|
const Id idx{index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index)};
|
||||||
|
const Id ptr{ctx.OpAccessChain(ctx.image_buffer_type, def.id, idx)};
|
||||||
|
return ctx.OpLoad(ctx.image_buffer_type, ptr);
|
||||||
}
|
}
|
||||||
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) {
|
||||||
throw NotImplementedException("Indirect texture sample");
|
const Id idx{index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index)};
|
||||||
|
const Id ptr{ctx.OpAccessChain(def.pointer_type, def.id, idx)};
|
||||||
|
return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, ptr));
|
||||||
}
|
}
|
||||||
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Id, bool> 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) {
|
||||||
|
const Id idx{index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index)};
|
||||||
|
const Id ptr{ctx.OpAccessChain(def.pointer_type, def.id, idx)};
|
||||||
|
return {ctx.OpLoad(def.image_type, ptr), def.is_integer};
|
||||||
|
}
|
||||||
return {ctx.OpLoad(def.image_type, def.id), def.is_integer};
|
return {ctx.OpLoad(def.image_type, def.id), def.is_integer};
|
||||||
} else {
|
} else {
|
||||||
const ImageDefinition def{ctx.images.at(info.descriptor_index)};
|
const ImageDefinition def{ctx.images.at(info.descriptor_index)};
|
||||||
|
if (def.count > 1) {
|
||||||
|
const Id idx{index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index)};
|
||||||
|
const Id ptr{ctx.OpAccessChain(def.pointer_type, def.id, idx)};
|
||||||
|
return {ctx.OpLoad(def.image_type, ptr), def.is_integer};
|
||||||
|
}
|
||||||
return {ctx.OpLoad(def.image_type, def.id), def.is_integer};
|
return {ctx.OpLoad(def.image_type, def.id), def.is_integer};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1331,9 +1331,6 @@ void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) {
|
||||||
void EmitContext::DefineImageBuffers(const Info& info, u32& binding) {
|
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) {
|
|
||||||
throw NotImplementedException("Array of image buffers");
|
|
||||||
}
|
|
||||||
const spv::ImageFormat format{GetImageFormat(desc.format)};
|
const spv::ImageFormat format{GetImageFormat(desc.format)};
|
||||||
const Id sampled_type{desc.is_integer ? U32[1] : F32[1]};
|
const Id sampled_type{desc.is_integer ? U32[1] : F32[1]};
|
||||||
const Id image_type{
|
const Id image_type{
|
||||||
|
|
@ -1346,6 +1343,7 @@ 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,
|
.is_integer = desc.is_integer,
|
||||||
});
|
});
|
||||||
|
|
@ -1389,9 +1387,6 @@ void EmitContext::DefineTextures(const Info& info, u32& binding, u32& scaling_in
|
||||||
void EmitContext::DefineImages(const Info& info, u32& binding, u32& scaling_index) {
|
void EmitContext::DefineImages(const Info& info, u32& binding, u32& scaling_index) {
|
||||||
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) {
|
|
||||||
throw NotImplementedException("Array of images");
|
|
||||||
}
|
|
||||||
const Id sampled_type{desc.is_integer ? U32[1] : F32[1]};
|
const Id sampled_type{desc.is_integer ? U32[1] : F32[1]};
|
||||||
const Id image_type{ImageType(*this, desc, sampled_type)};
|
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)};
|
||||||
|
|
@ -1402,6 +1397,7 @@ void EmitContext::DefineImages(const Info& info, u32& binding, u32& scaling_inde
|
||||||
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,
|
.is_integer = desc.is_integer,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ struct TextureBufferDefinition {
|
||||||
struct ImageBufferDefinition {
|
struct ImageBufferDefinition {
|
||||||
Id id;
|
Id id;
|
||||||
Id image_type;
|
Id image_type;
|
||||||
|
Id pointer_type;
|
||||||
u32 count;
|
u32 count;
|
||||||
bool is_integer;
|
bool is_integer;
|
||||||
};
|
};
|
||||||
|
|
@ -58,6 +59,7 @@ struct ImageBufferDefinition {
|
||||||
struct ImageDefinition {
|
struct ImageDefinition {
|
||||||
Id id;
|
Id id;
|
||||||
Id image_type;
|
Id image_type;
|
||||||
|
Id pointer_type;
|
||||||
u32 count;
|
u32 count;
|
||||||
bool is_integer;
|
bool is_integer;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue