mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-11-08 06:31:05 +01:00
[shader_recompiler, renderer_vulkan] draw sprites whose texture handle comes from a vertex attribute (#4566)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md).
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.
-------------------
credit: Ghael-V
Draw sprites whose texture handle comes from a vertex attribute. A bindless handle read from an interpolated vertex attribute could not be tracked to a constant buffer, so pipeline creation threw and every draw using the shader was dropped (FIFA player indicators, shadows and some text).
The handle now gets a sentinel descriptor, and the Vulkan rasterizer splits a triangle-list draw into runs of vertices that share a handle and binds each run's texture before drawing it.
4fec247e9e
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4566
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
This commit is contained in:
parent
be21ccce25
commit
3d3ed4b7d1
8 changed files with 189 additions and 12 deletions
|
|
@ -322,6 +322,10 @@ static inline u32 ReadCbufCached(Environment& env, u32 index, u32 offset) {
|
|||
return v;
|
||||
}
|
||||
|
||||
static inline bool IsAttributeHandle(const ConstBufferAddr& cbuf) {
|
||||
return cbuf.index == ATTRIBUTE_HANDLE_CBUF_INDEX;
|
||||
}
|
||||
|
||||
static inline u32 GetTextureHandleCached(Environment& env, const ConstBufferAddr& cbuf) {
|
||||
// Must all be uniquely different variables
|
||||
// If has secondary, then it will be cbuf.secondary_{index|offset}, else its 0.
|
||||
|
|
@ -341,14 +345,23 @@ static inline u32 GetTextureHandleCached(Environment& env, const ConstBufferAddr
|
|||
|
||||
// Cached variants of existing helpers
|
||||
static inline TextureType ReadTextureTypeCached(Environment& env, const ConstBufferAddr& cbuf) {
|
||||
if (IsAttributeHandle(cbuf)) {
|
||||
return TextureType::Color2D;
|
||||
}
|
||||
return env.ReadTextureType(GetTextureHandleCached(env, cbuf));
|
||||
}
|
||||
static inline TexturePixelFormat ReadTexturePixelFormatCached(Environment& env,
|
||||
const ConstBufferAddr& cbuf) {
|
||||
if (IsAttributeHandle(cbuf)) {
|
||||
return TexturePixelFormat::A8B8G8R8_UNORM;
|
||||
}
|
||||
return env.ReadTexturePixelFormat(GetTextureHandleCached(env, cbuf));
|
||||
}
|
||||
static inline bool IsTexturePixelFormatIntegerCached(Environment& env,
|
||||
const ConstBufferAddr& cbuf) {
|
||||
if (IsAttributeHandle(cbuf)) {
|
||||
return false;
|
||||
}
|
||||
return env.IsTexturePixelFormatInteger(GetTextureHandleCached(env, cbuf));
|
||||
}
|
||||
|
||||
|
|
@ -520,15 +533,43 @@ std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst, Environme
|
|||
};
|
||||
}
|
||||
|
||||
bool IsAttributeSourcedHandle(const IR::Value& handle) {
|
||||
if (handle.IsImmediate()) {
|
||||
return false;
|
||||
}
|
||||
const IR::Inst* inst{handle.InstRecursive()};
|
||||
if (inst->GetOpcode() == IR::Opcode::BitCastU32F32 && !inst->Arg(0).IsImmediate()) {
|
||||
inst = inst->Arg(0).InstRecursive();
|
||||
}
|
||||
return inst->GetOpcode() == IR::Opcode::GetAttribute ||
|
||||
inst->GetOpcode() == IR::Opcode::GetAttributeU32;
|
||||
}
|
||||
|
||||
TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst, const HostTranslateInfo& host_info) {
|
||||
ConstBufferAddr addr;
|
||||
if (IsBindless(inst)) {
|
||||
const std::optional<ConstBufferAddr> track_addr{TrackCached(inst.Arg(0), env, host_info, block)};
|
||||
|
||||
if (!track_addr) {
|
||||
throw NotImplementedException("Failed to track bindless texture constant buffer");
|
||||
} else {
|
||||
if (track_addr) {
|
||||
addr = *track_addr;
|
||||
} else if (host_info.support_attribute_texture_handle &&
|
||||
IsAttributeSourcedHandle(inst.Arg(0))) {
|
||||
// The handle travels with the vertices (sprite batches pick the texture per quad), so
|
||||
// there is no constant buffer to read it from. The host binds the handle of each run
|
||||
// of vertices that share one.
|
||||
addr = ConstBufferAddr{
|
||||
.index = ATTRIBUTE_HANDLE_CBUF_INDEX,
|
||||
.offset = 0,
|
||||
.shift_left = 0,
|
||||
.secondary_index = 0,
|
||||
.secondary_offset = 0,
|
||||
.secondary_shift_left = 0,
|
||||
.dynamic_offset = {},
|
||||
.count = 1,
|
||||
.has_secondary = false,
|
||||
};
|
||||
} else {
|
||||
throw NotImplementedException("Failed to track bindless texture constant buffer");
|
||||
}
|
||||
} else {
|
||||
addr = ConstBufferAddr{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue