diff --git a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h index 1a364f26..41d882fe 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h @@ -511,6 +511,47 @@ namespace skyline::gpu::interconnect { } } + /* Constant Buffers */ + private: + struct ConstantBuffer { + IOVA iova; + u32 size; + GuestBuffer guest; + std::shared_ptr 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 */ private: struct Shader { diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp index 83b3b2e2..55eb8798 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp @@ -47,6 +47,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { void Maxwell3D::HandleMethod(u32 method, u32 argument) { #define MAXWELL3D_OFFSET(field) (sizeof(typeof(Registers::field)) - sizeof(std::remove_reference_t)) / sizeof(u32) #define MAXWELL3D_STRUCT_OFFSET(field, member) MAXWELL3D_OFFSET(field) + U32_OFFSET(std::remove_reference_t, member) + #define MAXWELL3D_STRUCT_STRUCT_OFFSET(field, member, submember) MAXWELL3D_STRUCT_OFFSET(field, member) + U32_OFFSET(std::remove_reference_tmember)>, submember) #define MAXWELL3D_ARRAY_OFFSET(field, index) MAXWELL3D_OFFSET(field) + ((sizeof(std::remove_reference_t) / sizeof(u32)) * index) #define MAXWELL3D_ARRAY_STRUCT_OFFSET(field, index, member) MAXWELL3D_ARRAY_OFFSET(field, index) + U32_OFFSET(std::remove_reference_t, 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) @@ -62,6 +63,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { return; \ } #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_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) @@ -433,6 +435,18 @@ namespace skyline::soc::gm20b::engine::maxwell3d { 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: break; } diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h index fcd44bff..a9abad56 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h @@ -281,6 +281,12 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x800, std::array> setProgram; Register<0x8C0, u32[0x20]> firmwareCall; + + struct ConstantBufferSelector { + u32 size; + type::Address address; + }; + Register<0x8E0, ConstantBufferSelector> constantBufferSelector; }; static_assert(sizeof(Registers) == (RegisterCount * sizeof(u32))); #pragma pack(pop)