Implement Maxwell3D Constant Buffer Selector

The Constant Buffer Selector is used to point to a constant buffer that will be bound to a shader stage or updated with inline data.
This commit is contained in:
PixelyIon 2021-12-11 12:57:30 +05:30
parent afa34e320a
commit 9af9f1d41a
3 changed files with 61 additions and 0 deletions

View File

@ -511,6 +511,47 @@ namespace skyline::gpu::interconnect {
} }
} }
/* Constant Buffers */
private:
struct ConstantBuffer {
IOVA iova;
u32 size;
GuestBuffer guest;
std::shared_ptr<BufferView> view;
};
ConstantBuffer constantBufferSelector; //!< The constant buffer selector is used to bind a constant buffer to a stage or update data in it
public:
void SetConstantBufferSelectorSize(u32 size) {
constantBufferSelector.size = size;
constantBufferSelector.view.reset();
}
void SetConstantBufferSelectorIovaHigh(u32 high) {
constantBufferSelector.iova.high = high;
constantBufferSelector.view.reset();
}
void SetConstantBufferSelectorIovaLow(u32 low) {
constantBufferSelector.iova.low = low;
constantBufferSelector.view.reset();
}
BufferView *GetConstantBufferSelectorView() {
if (constantBufferSelector.size == 0)
return nullptr;
else if (constantBufferSelector.view)
return &*constantBufferSelector.view;
if (constantBufferSelector.guest.mappings.empty()) {
auto mappings{channelCtx.asCtx->gmmu.TranslateRange(constantBufferSelector.iova, constantBufferSelector.size)};
constantBufferSelector.guest.mappings.assign(mappings.begin(), mappings.end());
}
constantBufferSelector.view = gpu.buffer.FindOrCreate(constantBufferSelector.guest);
return constantBufferSelector.view.get();
}
/* Shader Program */ /* Shader Program */
private: private:
struct Shader { struct Shader {

View File

@ -47,6 +47,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
void Maxwell3D::HandleMethod(u32 method, u32 argument) { void Maxwell3D::HandleMethod(u32 method, u32 argument) {
#define MAXWELL3D_OFFSET(field) (sizeof(typeof(Registers::field)) - sizeof(std::remove_reference_t<decltype(*Registers::field)>)) / sizeof(u32) #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_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_ARRAY_OFFSET(field, index) MAXWELL3D_OFFSET(field) + ((sizeof(std::remove_reference_t<decltype(Registers::field[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_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) #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)
@ -62,6 +63,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
return; \ return; \
} }
#define MAXWELL3D_STRUCT_CASE(field, member, content) MAXWELL3D_CASE_BASE(member, field->member, MAXWELL3D_STRUCT_OFFSET(field, member), content) #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_ARRAY_CASE(field, index, content) MAXWELL3D_CASE_BASE(field, field[index], MAXWELL3D_ARRAY_OFFSET(field, 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_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) #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)
@ -433,6 +435,18 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
context.SetPrimitiveTopology(vertexBeginGl.topology); context.SetPrimitiveTopology(vertexBeginGl.topology);
}) })
MAXWELL3D_STRUCT_CASE(constantBufferSelector, size, {
context.SetConstantBufferSelectorSize(size);
})
MAXWELL3D_STRUCT_STRUCT_CASE(constantBufferSelector, address, high, {
context.SetConstantBufferSelectorIovaHigh(high);
})
MAXWELL3D_STRUCT_STRUCT_CASE(constantBufferSelector, address, low, {
context.SetConstantBufferSelectorIovaLow(low);
})
default: default:
break; break;
} }

View File

@ -281,6 +281,12 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0x800, std::array<type::SetProgramInfo, type::StageCount>> setProgram; Register<0x800, std::array<type::SetProgramInfo, type::StageCount>> setProgram;
Register<0x8C0, u32[0x20]> firmwareCall; Register<0x8C0, u32[0x20]> firmwareCall;
struct ConstantBufferSelector {
u32 size;
type::Address address;
};
Register<0x8E0, ConstantBufferSelector> constantBufferSelector;
}; };
static_assert(sizeof(Registers) == (RegisterCount * sizeof(u32))); static_assert(sizeof(Registers) == (RegisterCount * sizeof(u32)));
#pragma pack(pop) #pragma pack(pop)