summaryrefslogtreecommitdiffstats
path: root/src/video_core/engines
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/engines')
-rw-r--r--src/video_core/engines/maxwell_3d.cpp26
-rw-r--r--src/video_core/engines/maxwell_3d.h25
2 files changed, 39 insertions, 12 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 7357d20d1..d79c50919 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -43,15 +43,17 @@ void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
// Reset the current macro.
executing_macro = 0;
- // The requested macro must have been uploaded already.
- auto macro_code = uploaded_macros.find(method);
- if (macro_code == uploaded_macros.end()) {
- LOG_ERROR(HW_GPU, "Macro {:04X} was not uploaded", method);
+ // Lookup the macro offset
+ const u32 entry{(method - MacroRegistersStart) >> 1};
+ const auto& search{macro_offsets.find(entry)};
+ if (search == macro_offsets.end()) {
+ LOG_CRITICAL(HW_GPU, "macro not found for method 0x{:X}!", method);
+ UNREACHABLE();
return;
}
// Execute the current macro.
- macro_interpreter.Execute(macro_code->second, std::move(parameters));
+ macro_interpreter.Execute(search->second, std::move(parameters));
}
void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
@@ -97,6 +99,10 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
ProcessMacroUpload(value);
break;
}
+ case MAXWELL3D_REG_INDEX(macros.bind): {
+ ProcessMacroBind(value);
+ break;
+ }
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[0]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[1]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[2]):
@@ -158,9 +164,13 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
}
void Maxwell3D::ProcessMacroUpload(u32 data) {
- // Store the uploaded macro code to interpret them when they're called.
- auto& macro = uploaded_macros[regs.macros.entry * 2 + MacroRegistersStart];
- macro.push_back(data);
+ ASSERT_MSG(regs.macros.upload_address < macro_memory.size(),
+ "upload_address exceeded macro_memory size!");
+ macro_memory[regs.macros.upload_address++] = data;
+}
+
+void Maxwell3D::ProcessMacroBind(u32 data) {
+ macro_offsets[regs.macros.entry] = data;
}
void Maxwell3D::ProcessQueryGet() {
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 443affc36..50873813e 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -475,12 +475,13 @@ public:
INSERT_PADDING_WORDS(0x45);
struct {
- INSERT_PADDING_WORDS(1);
+ u32 upload_address;
u32 data;
u32 entry;
+ u32 bind;
} macros;
- INSERT_PADDING_WORDS(0x189);
+ INSERT_PADDING_WORDS(0x188);
u32 tfb_enabled;
@@ -994,12 +995,25 @@ public:
/// Returns the texture information for a specific texture in a specific shader stage.
Texture::FullTextureInfo GetStageTexture(Regs::ShaderStage stage, std::size_t offset) const;
+ /// Memory for macro code - it's undetermined how big this is, however 1MB is much larger than
+ /// we've seen used.
+ using MacroMemory = std::array<u32, 0x40000>;
+
+ /// Gets a reference to macro memory.
+ const MacroMemory& GetMacroMemory() const {
+ return macro_memory;
+ }
+
private:
void InitializeRegisterDefaults();
VideoCore::RasterizerInterface& rasterizer;
- std::unordered_map<u32, std::vector<u32>> uploaded_macros;
+ /// Start offsets of each macro in macro_memory
+ std::unordered_map<u32, u32> macro_offsets;
+
+ /// Memory for macro code
+ MacroMemory macro_memory;
/// Macro method that is currently being executed / being fed parameters.
u32 executing_macro = 0;
@@ -1022,9 +1036,12 @@ private:
*/
void CallMacroMethod(u32 method, std::vector<u32> parameters);
- /// Handles writes to the macro uploading registers.
+ /// Handles writes to the macro uploading register.
void ProcessMacroUpload(u32 data);
+ /// Handles writes to the macro bind register.
+ void ProcessMacroBind(u32 data);
+
/// Handles a write to the CLEAR_BUFFERS register.
void ProcessClearBuffers();