我开始学习 Direct3D 12,但难以理解 CPU-GPU 同步。据我了解,fence(ID3D12Fence)只不过是用作计数器的UINT64(unsigned long long)值。但它的方法让我困惑。以下是D3D12示例的部分源代码。( https://github.com/d3dcoder/d3d12book )
void D3DApp::FlushCommandQueue()
{
// Advance the fence value to mark commands up to this fence point.
mCurrentFence++;
// Add an instruction to the command queue to set a new fence point. Because we
// are on the GPU timeline, the new fence point won't be set until the GPU finishes
// processing all the commands prior to this Signal().
ThrowIfFailed(mCommandQueue->Signal(mFence.Get(), mCurrentFence));
// Wait until the GPU has completed commands up to …Run Code Online (Sandbox Code Playgroud) 静态局部变量如何在不同的翻译单元中共享?
我知道“静态”指定内部链接。
如果“静态”成员函数在不同的翻译单元中具有相同的地址,则每个翻译单元都有该函数的副本,并且链接器选择要包含在可执行文件中的副本之一。
然后,在两个不同翻译包含 1 个共享标头的情况下,该共享标头有一个带有静态成员函数的类,该静态成员函数会递增静态局部变量,并且每个翻译单元(cpp)调用共享标头的静态成员函数,每个翻译单元将增加自己的独立静态局部变量,因为 static 指定内部链接。例如,
共享.h
#pragma once
class CShared
{
public:
static inline void Foo()
{
static int s_nCount = 0;
++s_nCount;
}
private:
CShared(){}
~CShared(){}
};
Run Code Online (Sandbox Code Playgroud)
啊
#pragma once
class A
{
public:
A(){}
~A(){}
void Foo();
};
Run Code Online (Sandbox Code Playgroud)
a.cpp
#include "A.h"
#include "Shared.h"
void A::Foo()
{
CShared::Foo();
}
Run Code Online (Sandbox Code Playgroud)
巴赫
#pragma once
class B
{
public:
B(){}
~B(){}
void Foo();
};
Run Code Online (Sandbox Code Playgroud)
B.cpp
#include "B.h"
#include "Shared.h"
void B::Foo()
{
CShared::Foo();
}
Run Code Online (Sandbox Code Playgroud)
主程序 …
这个问题的表达方式和什么是 UEFI 的启动顺序一样?,但似乎不是我想要的。我想从指令的角度了解 UEFI 序列。
例如,在 BIOS 引导模式的情况下,以简化的方式,
相关文章:https : //neosmart.net/wiki/mbr-boot-process/
但,
在 UEFI 的情况下,我很难掌握这个顺序。
我已经浏览了 UEFI 规范文档和 OS Dev UEFI 部分。
UEFI:https : //uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf
操作系统开发:https : //wiki.osdev.org/UEFI
似乎这个 efi_main() 函数在 BIOS 模式下相当于 0x7C00 的点。但是如何?
UEFI固件是否在做类似的事情
jmp efi_main
在完成一系列工作之后?
一季度。UEFI 启动模式的流程如何?
Q2。是否有一个很好的 UEFI 示例或教程,例如基于 BIOS 的 Brokenthorn?
聚苯乙烯
我已经看到了英特尔在 2020 年取消 BIOS 支持的消息(这些年已经过去了)。
https://www.anandtech.com/show/12068/intel-to-remove-bios-support-from-uefi-by-2020
它说 …
这个问题的原始目标是
到目前为止,我了解的是(x86英特尔架构Z370芯片组)
我想做的是
但是,几乎没有涉及I / O端口的文章,而且还不够。
Q1。是否有一些文章或书充分解释了使用IN和OUT指令进行I / O端口交互?
找到的文章是
断刺
http://www.brokenthorn.com/Resources/OSDev7.html
http://www.brokenthorn.com/Resources/OSDev9.html
操作系统开发
https://wiki.osdev.org/I/O_Ports
https://wiki.osdev.org/%228042%22_PS/2_Controller
我之所以需要更详细的文章,是因为我有这样的问题,例如是否插入了2个USB键盘,如果0x60可以访问一个,那么如何访问其他键盘呢?可以通过命令检查启用的设备,但是是否必须先进行设备存在性/连接检查?
Q2。另外,这些端口似乎没有像PCI Configuration Header这样的标准,那么如何处理其他端口?
即使是一小部分的答案,也将不胜感激。
PS也许我想做的是编写位于I / O端口(= I / O设备控制器)<-> I / O设备驱动程序之间的阶段的逻辑。这项工作似乎由ACPICA的ACPI完成。但是我希望自己在集会上自己做。
struct SGetWindow
{
HWND__* pWindow;
};
Run Code Online (Sandbox Code Playgroud)
SGetWindow getWindow;
EnumWindows(GetWindowProc, reinterpret_cast<LParam>(&getWindow));
return getWindow.pWindow;
Run Code Online (Sandbox Code Playgroud)
使用 SGetWindow 结构体作为 LParam,成功更新 HWND__* pWindow。
我想知道这种返回局部结构变量的成员变量的用法是否安全。
return getwindow.pWindow;
Run Code Online (Sandbox Code Playgroud)
安全吗?或导致未定义的行为?
编辑:我添加了一个图像以供理解。
我了解到指针的值(0x00000000000506D8 或 0x00000000000606D8)1)在函数终止后有效,2)将被复制。但我认为这并不能保证安全性,因为问题似乎是“访问(不再存在的本地结构成员变量),并返回其值”。
编辑2:
我想错了,我太笨了。
根据我的想法,即使返回本地 int 变量也会导致未定义的行为。例如,
int func()
{
int a = 10;
return a;
}
Run Code Online (Sandbox Code Playgroud)
函数退出时,局部变量“a”不再有效。因此,返回值是未定义的行为。
然而,这不是。因为它是“按值返回”类型。值被复制(某处),复制过程是在局部变量超出范围之前。
操作顺序类似于
2. 将局部变量的值复制到“某处”。
“按值返回的另一个优点是您可以返回涉及在函数内声明的局部变量的变量(或表达式),而不必担心作用域问题。因为在函数返回之前评估变量,并且值的副本是返回给调用者,当函数的变量在函数结束时超出范围时,没有问题。 ”
https://www.learncpp.com/cpp-tutorial/74a-returning-values-by-value-reference-and-address/
“函数调用结果的复制初始化顺序在表达式末尾的所有临时变量的销毁之前,反过来,在包含 return 语句的块的局部变量的销毁之前。”
https://en.cppreference.com/w/cpp/language/return
EBP 还原
https://en.wikibooks.org/wiki/X86_Disassembly/Functions_and_Stack_Frames
耻辱我!顺便感谢您的友好回答。
我正在尝试定义一个具有私有结构和公共结构的类。
私有结构是仅由类使用的结构(例如 SNode),我不希望它在类外可见,因为我不希望它被错误地使用(例如 new Node())。因此,我想到了将其设置为基本隐藏的想法。
公共结构是将在外部使用的结构(例如 SKeyValuePair),它将有一个指向 SNode 的指针。
代码示例如下。
[类定义]
template <typename T>
class A
{
private:
struct SNode
{
SNode* pParentNode;
SNode* pLeftChildNode;
SNode* pRightChildNode;
...
};
public:
A<T>()
{
}
virtual ~A()
{
}
struct SPair
{
private:
public:
SNode* pNode;
unsigned long long ullKey;
T value;
...
};
const SPair GetMinKeyPair()
{
return SPair(...);
}
const SPair GetNextMinKeyPair()
{
...
return SPair(...);
}
};
Run Code Online (Sandbox Code Playgroud)
[用法]
A a;
...
for (A::SPair pair = a.GetMinKeyPair(); pair.pNode …Run Code Online (Sandbox Code Playgroud) 为了访问PCI配置空间,根据各种文章,使用I / O端口地址0xCF8、0xCFC。
mov eax, dword 0x80000000
mov dx, word 0x0CF8
out dx, eax
mov dx, word 0x0CFC
in eax, dx
Run Code Online (Sandbox Code Playgroud)
上面代码中eax的值是0x12378086,表示vendor ID = 0x8086和device ID = 0x1237。
这是问题。
Q1。我已经看到此方法仅适用于PCI配置空间。那么,访问PCIe配置空间的另一种方法是什么?
“ 无法使用传统的PCI方法(通过端口0xCF8和0xCFC)访问此扩展的配置空间”
https://wiki.osdev.org/PCI_Express
但是另一些文章说,这种传统方法也与PCIe配置空间兼容。
这很混乱。
Q2。如果传统的0xCF8、0xCFC也可以与PCIe配置空间配合使用,那么将不胜枚举NASM汇编源代码(不涉及linux),因为我看过很多ECAM(增强型配置访问机制)文章,但所有这些都是关于概念性内容。
硬件规格:
Motherboard : P775TM1
Processor : Intel i7 8700K
Run Code Online (Sandbox Code Playgroud)