mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-26 15:54:18 +01:00
Implement CPU-only Maxwell3D Inline Constant Buffer Updates
Implements inline constant buffer updates that are written to the CPU copy of the buffer rather than generating an actual inline buffer write, this works for TIC/TSC index updates but won't work when the buffer is expected to actually be updated inline with regard to sequence rather than just as a buffer upload prior to rendering. GPU-sided constant buffer updates will be implemented later with optimizations for updating an entire range by handling GPFIFO `Inc`/`NonInc`directly and submitting it as a host inline buffer update.
This commit is contained in:
parent
08f29f7da4
commit
bc29b23972
@ -543,9 +543,33 @@ namespace skyline::gpu::interconnect {
|
||||
}
|
||||
throw exception("Object extent ({} + {} = {}) is larger than constant buffer size: {}", size + offset, sizeof(T), size + offset + sizeof(T), size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes an object to the supplied offset in the constant buffer
|
||||
* @note This must only be called when the GuestBuffer is resolved correctly
|
||||
*/
|
||||
template<typename T>
|
||||
void Write(const T &object, size_t offset) {
|
||||
size_t objectOffset{};
|
||||
for (auto &mapping: guest.mappings) {
|
||||
if (offset < mapping.size_bytes()) {
|
||||
auto copySize{std::min(mapping.size_bytes() - offset, sizeof(T))};
|
||||
std::memcpy(mapping.data() + offset, reinterpret_cast<const u8 *>(&object) + objectOffset, copySize);
|
||||
objectOffset += copySize;
|
||||
if (objectOffset == sizeof(T))
|
||||
return;
|
||||
offset = mapping.size_bytes();
|
||||
} else {
|
||||
offset -= mapping.size_bytes();
|
||||
}
|
||||
}
|
||||
throw exception("Object extent ({} + {} = {}) is larger than constant buffer size: {}", size + offset, sizeof(T), size + offset + sizeof(T), size);
|
||||
}
|
||||
};
|
||||
ConstantBuffer constantBufferSelector; //!< The constant buffer selector is used to bind a constant buffer to a stage or update data in it
|
||||
|
||||
u32 constantBufferUpdateOffset{}; //!< The offset at which any inline constant buffer updata data is written
|
||||
|
||||
public:
|
||||
void SetConstantBufferSelectorSize(u32 size) {
|
||||
constantBufferSelector.size = size;
|
||||
@ -575,6 +599,15 @@ namespace skyline::gpu::interconnect {
|
||||
return constantBufferSelector;
|
||||
}
|
||||
|
||||
void SetConstantBufferUpdateOffset(u32 offset) {
|
||||
constantBufferUpdateOffset = offset;
|
||||
}
|
||||
|
||||
void ConstantBufferUpdate(u32 data) {
|
||||
auto constantBuffer{GetConstantBufferSelector().value()};
|
||||
constantBuffer.Write(data, constantBufferUpdateOffset);
|
||||
}
|
||||
|
||||
/* Shader Program */
|
||||
private:
|
||||
struct Shader {
|
||||
|
@ -48,6 +48,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
||||
#define MAXWELL3D_OFFSET(field) (sizeof(typeof(Registers::field)) - sizeof(std::remove_reference_t<decltype(*Registers::field)>)) / sizeof(u32)
|
||||
#define MAXWELL3D_STRUCT_OFFSET(field, member) MAXWELL3D_OFFSET(field) + U32_OFFSET(std::remove_reference_t<decltype(*Registers::field)>, member)
|
||||
#define MAXWELL3D_STRUCT_STRUCT_OFFSET(field, member, submember) MAXWELL3D_STRUCT_OFFSET(field, member) + U32_OFFSET(std::remove_reference_t<decltype(Registers::field->member)>, submember)
|
||||
#define MAXWELL3D_STRUCT_ARRAY_OFFSET(field, member, index) MAXWELL3D_STRUCT_OFFSET(field, member) + ((sizeof(std::remove_reference_t<decltype(Registers::field->member[0])>) / sizeof(u32)) * index)
|
||||
#define MAXWELL3D_ARRAY_OFFSET(field, index) MAXWELL3D_OFFSET(field) + ((sizeof(std::remove_reference_t<decltype(Registers::field[0])>) / sizeof(u32)) * index)
|
||||
#define MAXWELL3D_ARRAY_STRUCT_OFFSET(field, index, member) MAXWELL3D_ARRAY_OFFSET(field, index) + U32_OFFSET(std::remove_reference_t<decltype(Registers::field[0])>, member)
|
||||
#define MAXWELL3D_ARRAY_STRUCT_STRUCT_OFFSET(field, index, member, submember) MAXWELL3D_ARRAY_STRUCT_OFFSET(field, index, member) + U32_OFFSET(decltype(Registers::field[0].member), submember)
|
||||
@ -64,6 +65,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
||||
}
|
||||
#define MAXWELL3D_STRUCT_CASE(field, member, content) MAXWELL3D_CASE_BASE(member, field->member, MAXWELL3D_STRUCT_OFFSET(field, member), content)
|
||||
#define MAXWELL3D_STRUCT_STRUCT_CASE(field, member, submember, content) MAXWELL3D_CASE_BASE(submember, field->member.submember, MAXWELL3D_STRUCT_STRUCT_OFFSET(field, member, submember), content)
|
||||
#define MAXWELL3D_STRUCT_ARRAY_CASE(field, member, index, content) MAXWELL3D_CASE_BASE(member, field->member[index], MAXWELL3D_STRUCT_ARRAY_OFFSET(field, member, index), content)
|
||||
#define MAXWELL3D_ARRAY_CASE(field, index, content) MAXWELL3D_CASE_BASE(field, field[index], MAXWELL3D_ARRAY_OFFSET(field, index), content)
|
||||
#define MAXWELL3D_ARRAY_STRUCT_CASE(field, index, member, content) MAXWELL3D_CASE_BASE(member, field[index].member, MAXWELL3D_ARRAY_STRUCT_OFFSET(field, index, member), content)
|
||||
#define MAXWELL3D_ARRAY_STRUCT_STRUCT_CASE(field, index, member, submember, content) MAXWELL3D_CASE_BASE(submember, field[index].member.submember, MAXWELL3D_ARRAY_STRUCT_STRUCT_OFFSET(field, index, member, submember), content)
|
||||
@ -487,6 +489,10 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
||||
context.SetTexturePoolMaximumIndex(maximumIndex);
|
||||
})
|
||||
|
||||
MAXWELL3D_STRUCT_CASE(constantBufferUpdate, offset, {
|
||||
context.SetConstantBufferUpdateOffset(offset);
|
||||
})
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -575,12 +581,21 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
||||
registers.raw[0xD00] = 1;
|
||||
})
|
||||
|
||||
#define CBUF_UPDATE_CALLBACKS(z, index, data_) \
|
||||
MAXWELL3D_STRUCT_ARRAY_CASE(constantBufferUpdate, data, index, { \
|
||||
context.ConstantBufferUpdate(data); \
|
||||
})
|
||||
|
||||
BOOST_PP_REPEAT(16, CBUF_UPDATE_CALLBACKS, 0)
|
||||
#undef CBUF_UPDATE_CALLBACKS
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#undef MAXWELL3D_OFFSET
|
||||
#undef MAXWELL3D_STRUCT_OFFSET
|
||||
#undef MAXWELL3D_STRUCT_ARRAY_OFFSET
|
||||
#undef MAXWELL3D_ARRAY_OFFSET
|
||||
#undef MAXWELL3D_ARRAY_STRUCT_OFFSET
|
||||
#undef MAXWELL3D_ARRAY_STRUCT_STRUCT_OFFSET
|
||||
@ -588,6 +603,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
||||
#undef MAXWELL3D_CASE_BASE
|
||||
#undef MAXWELL3D_CASE
|
||||
#undef MAXWELL3D_STRUCT_CASE
|
||||
#undef MAXWELL3D_STRUCT_ARRAY_CASE
|
||||
#undef MAXWELL3D_ARRAY_CASE
|
||||
#undef MAXWELL3D_ARRAY_STRUCT_CASE
|
||||
#undef MAXWELL3D_ARRAY_STRUCT_STRUCT_CASE
|
||||
|
@ -293,6 +293,15 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
||||
};
|
||||
Register<0x8E0, ConstantBufferSelector> constantBufferSelector;
|
||||
|
||||
/**
|
||||
* @brief Allows updating the currently selected constant buffer inline with an offset and up to 16 words of data
|
||||
*/
|
||||
struct ConstantBufferUpdate {
|
||||
u32 offset;
|
||||
std::array<u32, 16> data;
|
||||
};
|
||||
Register<0x8E3, ConstantBufferUpdate> constantBufferUpdate;
|
||||
|
||||
Register<0x900, std::array<type::Bind, type::PipelineStageCount>> bind; //!< Binds constant buffers to pipeline stages
|
||||
|
||||
Register<0x982, u32> bindlessTextureConstantBufferIndex; //!< The index of the constant buffer containing bindless texture descriptors
|
||||
|
Loading…
Reference in New Issue
Block a user