mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-02 20:51:45 +00:00
Introduce Begin/EndComputePass (#70)
This commit is contained in:
parent
afdcf7d828
commit
296951df60
@ -264,11 +264,13 @@ void initCommandBuffers() {
|
||||
auto& bufferSrc = particleBuffers[i];
|
||||
auto& bufferDst = particleBuffers[(i + 1) % 2];
|
||||
commandBuffers[i] = device.CreateCommandBufferBuilder()
|
||||
.SetPipeline(updatePipeline)
|
||||
.TransitionBufferUsage(bufferSrc, nxt::BufferUsageBit::Storage)
|
||||
.TransitionBufferUsage(bufferDst, nxt::BufferUsageBit::Storage)
|
||||
.SetBindGroup(0, updateBGs[i])
|
||||
.Dispatch(kNumParticles, 1, 1)
|
||||
.BeginComputePass()
|
||||
.SetPipeline(updatePipeline)
|
||||
.TransitionBufferUsage(bufferSrc, nxt::BufferUsageBit::Storage)
|
||||
.TransitionBufferUsage(bufferDst, nxt::BufferUsageBit::Storage)
|
||||
.SetBindGroup(0, updateBGs[i])
|
||||
.Dispatch(kNumParticles, 1, 1)
|
||||
.EndComputePass()
|
||||
|
||||
.BeginRenderPass(renderpass, framebuffer)
|
||||
.BeginRenderSubpass()
|
||||
|
@ -126,10 +126,12 @@ void init() {
|
||||
|
||||
void frame() {
|
||||
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
|
||||
.SetPipeline(computePipeline)
|
||||
.TransitionBufferUsage(buffer, nxt::BufferUsageBit::Storage)
|
||||
.SetBindGroup(0, computeBindGroup)
|
||||
.Dispatch(1, 1, 1)
|
||||
.BeginComputePass()
|
||||
.SetPipeline(computePipeline)
|
||||
.TransitionBufferUsage(buffer, nxt::BufferUsageBit::Storage)
|
||||
.SetBindGroup(0, computeBindGroup)
|
||||
.Dispatch(1, 1, 1)
|
||||
.EndComputePass()
|
||||
|
||||
.BeginRenderPass(renderpass, framebuffer)
|
||||
.BeginRenderSubpass()
|
||||
|
@ -247,6 +247,9 @@
|
||||
"name": "get result",
|
||||
"returns": "command buffer"
|
||||
},
|
||||
{
|
||||
"name": "begin compute pass"
|
||||
},
|
||||
{
|
||||
"name": "begin render pass",
|
||||
"args": [
|
||||
@ -340,6 +343,9 @@
|
||||
{"name": "first instance", "type": "uint32_t"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "end compute pass"
|
||||
},
|
||||
{
|
||||
"name": "end render pass"
|
||||
},
|
||||
|
@ -105,6 +105,12 @@ namespace backend {
|
||||
Command type;
|
||||
while(commands->NextCommandId(&type)) {
|
||||
switch (type) {
|
||||
case Command::BeginComputePass:
|
||||
{
|
||||
BeginComputePassCmd* begin = commands->NextCommand<BeginComputePassCmd>();
|
||||
begin->~BeginComputePassCmd();
|
||||
}
|
||||
break;
|
||||
case Command::BeginRenderPass:
|
||||
{
|
||||
BeginRenderPassCmd* begin = commands->NextCommand<BeginRenderPassCmd>();
|
||||
@ -153,6 +159,12 @@ namespace backend {
|
||||
draw->~DrawElementsCmd();
|
||||
}
|
||||
break;
|
||||
case Command::EndComputePass:
|
||||
{
|
||||
EndComputePassCmd* cmd = commands->NextCommand<EndComputePassCmd>();
|
||||
cmd->~EndComputePassCmd();
|
||||
}
|
||||
break;
|
||||
case Command::EndRenderPass:
|
||||
{
|
||||
EndRenderPassCmd* cmd = commands->NextCommand<EndRenderPassCmd>();
|
||||
@ -226,6 +238,10 @@ namespace backend {
|
||||
|
||||
void SkipCommand(CommandIterator* commands, Command type) {
|
||||
switch (type) {
|
||||
case Command::BeginComputePass:
|
||||
commands->NextCommand<BeginComputePassCmd>();
|
||||
break;
|
||||
|
||||
case Command::BeginRenderPass:
|
||||
commands->NextCommand<BeginRenderPassCmd>();
|
||||
break;
|
||||
@ -258,6 +274,10 @@ namespace backend {
|
||||
commands->NextCommand<DrawElementsCmd>();
|
||||
break;
|
||||
|
||||
case Command::EndComputePass:
|
||||
commands->NextCommand<EndComputePassCmd>();
|
||||
break;
|
||||
|
||||
case Command::EndRenderPass:
|
||||
commands->NextCommand<EndRenderPassCmd>();
|
||||
break;
|
||||
@ -323,6 +343,15 @@ namespace backend {
|
||||
Command type;
|
||||
while (iterator.NextCommandId(&type)) {
|
||||
switch (type) {
|
||||
case Command::BeginComputePass:
|
||||
{
|
||||
iterator.NextCommand<BeginComputePassCmd>();
|
||||
if (!state->BeginComputePass()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::BeginRenderPass:
|
||||
{
|
||||
BeginRenderPassCmd* cmd = iterator.NextCommand<BeginRenderPassCmd>();
|
||||
@ -424,6 +453,15 @@ namespace backend {
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::EndComputePass:
|
||||
{
|
||||
iterator.NextCommand<EndComputePassCmd>();
|
||||
if (!state->EndComputePass()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::EndRenderPass:
|
||||
{
|
||||
iterator.NextCommand<EndRenderPassCmd>();
|
||||
@ -542,8 +580,8 @@ namespace backend {
|
||||
return device->CreateCommandBuffer(this);
|
||||
}
|
||||
|
||||
void CommandBufferBuilder::BeginRenderSubpass() {
|
||||
allocator.Allocate<BeginRenderSubpassCmd>(Command::BeginRenderSubpass);
|
||||
void CommandBufferBuilder::BeginComputePass() {
|
||||
allocator.Allocate<BeginComputePassCmd>(Command::BeginComputePass);
|
||||
}
|
||||
|
||||
void CommandBufferBuilder::BeginRenderPass(RenderPassBase* renderPass, FramebufferBase* framebuffer) {
|
||||
@ -553,6 +591,10 @@ namespace backend {
|
||||
cmd->framebuffer = framebuffer;
|
||||
}
|
||||
|
||||
void CommandBufferBuilder::BeginRenderSubpass() {
|
||||
allocator.Allocate<BeginRenderSubpassCmd>(Command::BeginRenderSubpass);
|
||||
}
|
||||
|
||||
void CommandBufferBuilder::CopyBufferToBuffer(BufferBase* source, uint32_t sourceOffset, BufferBase* destination, uint32_t destinationOffset, uint32_t size) {
|
||||
CopyBufferToBufferCmd* copy = allocator.Allocate<CopyBufferToBufferCmd>(Command::CopyBufferToBuffer);
|
||||
new(copy) CopyBufferToBufferCmd;
|
||||
@ -623,6 +665,10 @@ namespace backend {
|
||||
draw->firstInstance = firstInstance;
|
||||
}
|
||||
|
||||
void CommandBufferBuilder::EndComputePass() {
|
||||
allocator.Allocate<EndComputePassCmd>(Command::EndComputePass);
|
||||
}
|
||||
|
||||
void CommandBufferBuilder::EndRenderPass() {
|
||||
allocator.Allocate<EndRenderPassCmd>(Command::EndRenderPass);
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ namespace backend {
|
||||
CommandIterator AcquireCommands();
|
||||
|
||||
// NXT API
|
||||
void BeginComputePass();
|
||||
void BeginRenderPass(RenderPassBase* renderPass, FramebufferBase* framebuffer);
|
||||
void BeginRenderSubpass();
|
||||
void CopyBufferToBuffer(BufferBase* source, uint32_t sourceOffset, BufferBase* destination, uint32_t destinationOffset, uint32_t size);
|
||||
@ -71,6 +72,7 @@ namespace backend {
|
||||
void Dispatch(uint32_t x, uint32_t y, uint32_t z);
|
||||
void DrawArrays(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance);
|
||||
void DrawElements(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstIndex, uint32_t firstInstance);
|
||||
void EndComputePass();
|
||||
void EndRenderPass();
|
||||
void EndRenderSubpass();
|
||||
void SetPushConstants(nxt::ShaderStageBit stage, uint32_t offset, uint32_t count, const void* data);
|
||||
|
@ -61,7 +61,7 @@ namespace backend {
|
||||
|
||||
bool CommandBufferStateTracker::ValidateCanDispatch() {
|
||||
constexpr ValidationAspects requiredAspects =
|
||||
1 << VALIDATION_ASPECT_COMPUTE_PIPELINE |
|
||||
1 << VALIDATION_ASPECT_COMPUTE_PIPELINE | // implicitly requires COMPUTE_PASS
|
||||
1 << VALIDATION_ASPECT_BIND_GROUPS;
|
||||
if ((requiredAspects & ~aspects).none()) {
|
||||
// Fast return-true path if everything is good
|
||||
@ -83,7 +83,7 @@ namespace backend {
|
||||
bool CommandBufferStateTracker::ValidateCanDrawArrays() {
|
||||
// TODO(kainino@chromium.org): Check for a current render pass
|
||||
constexpr ValidationAspects requiredAspects =
|
||||
1 << VALIDATION_ASPECT_RENDER_PIPELINE |
|
||||
1 << VALIDATION_ASPECT_RENDER_PIPELINE | // implicitly requires RENDER_SUBPASS
|
||||
1 << VALIDATION_ASPECT_BIND_GROUPS |
|
||||
1 << VALIDATION_ASPECT_VERTEX_BUFFERS;
|
||||
if ((requiredAspects & ~aspects).none()) {
|
||||
@ -118,6 +118,29 @@ namespace backend {
|
||||
builder->HandleError("Can't end command buffer with an active render pass");
|
||||
return false;
|
||||
}
|
||||
if (aspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
|
||||
builder->HandleError("Can't end command buffer with an active compute pass");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::BeginComputePass() {
|
||||
if (currentRenderPass != nullptr) {
|
||||
builder->HandleError("Cannot begin a compute pass while a render pass is active");
|
||||
return false;
|
||||
}
|
||||
aspects.set(VALIDATION_ASPECT_COMPUTE_PASS);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::EndComputePass() {
|
||||
if (!aspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
|
||||
builder->HandleError("Can't end a compute pass without beginning one");
|
||||
return false;
|
||||
}
|
||||
aspects.reset(VALIDATION_ASPECT_COMPUTE_PASS);
|
||||
UnsetPipeline();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -193,6 +216,10 @@ namespace backend {
|
||||
};
|
||||
|
||||
bool CommandBufferStateTracker::BeginRenderPass(RenderPassBase* renderPass, FramebufferBase* framebuffer) {
|
||||
if (aspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
|
||||
builder->HandleError("Cannot begin a render pass while a compute pass is active");
|
||||
return false;
|
||||
}
|
||||
if (currentRenderPass != nullptr) {
|
||||
builder->HandleError("A render pass is already active");
|
||||
return false;
|
||||
@ -207,7 +234,6 @@ namespace backend {
|
||||
currentFramebuffer = framebuffer;
|
||||
currentSubpass = 0;
|
||||
|
||||
UnsetPipeline();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -234,6 +260,10 @@ namespace backend {
|
||||
PipelineLayoutBase* layout = pipeline->GetLayout();
|
||||
|
||||
if (pipeline->IsCompute()) {
|
||||
if (!aspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
|
||||
builder->HandleError("A compute pass must be active when a compute pipeline is set");
|
||||
return false;
|
||||
}
|
||||
if (currentRenderPass) {
|
||||
builder->HandleError("Can't use a compute pipeline while a render pass is active");
|
||||
return false;
|
||||
|
@ -39,6 +39,8 @@ namespace backend {
|
||||
bool ValidateEndCommandBuffer() const;
|
||||
|
||||
// State-modifying methods
|
||||
bool BeginComputePass();
|
||||
bool EndComputePass();
|
||||
bool BeginSubpass();
|
||||
bool EndSubpass();
|
||||
bool BeginRenderPass(RenderPassBase* renderPass, FramebufferBase* framebuffer);
|
||||
@ -66,6 +68,7 @@ namespace backend {
|
||||
VALIDATION_ASPECT_VERTEX_BUFFERS,
|
||||
VALIDATION_ASPECT_INDEX_BUFFER,
|
||||
VALIDATION_ASPECT_RENDER_SUBPASS,
|
||||
VALIDATION_ASPECT_COMPUTE_PASS,
|
||||
|
||||
VALIDATION_ASPECT_COUNT
|
||||
};
|
||||
|
@ -28,6 +28,7 @@ namespace backend {
|
||||
// dependencies: Ref<Object> needs Object to be defined.
|
||||
|
||||
enum class Command {
|
||||
BeginComputePass,
|
||||
BeginRenderPass,
|
||||
BeginRenderSubpass,
|
||||
CopyBufferToBuffer,
|
||||
@ -36,6 +37,7 @@ namespace backend {
|
||||
Dispatch,
|
||||
DrawArrays,
|
||||
DrawElements,
|
||||
EndComputePass,
|
||||
EndRenderPass,
|
||||
EndRenderSubpass,
|
||||
SetPipeline,
|
||||
@ -48,6 +50,9 @@ namespace backend {
|
||||
TransitionTextureUsage,
|
||||
};
|
||||
|
||||
struct BeginComputePassCmd {
|
||||
};
|
||||
|
||||
struct BeginRenderPassCmd {
|
||||
Ref<RenderPassBase> renderPass;
|
||||
Ref<FramebufferBase> framebuffer;
|
||||
@ -104,6 +109,9 @@ namespace backend {
|
||||
uint32_t firstInstance;
|
||||
};
|
||||
|
||||
struct EndComputePassCmd {
|
||||
};
|
||||
|
||||
struct EndRenderPassCmd {
|
||||
};
|
||||
|
||||
|
@ -253,6 +253,12 @@ namespace d3d12 {
|
||||
|
||||
while(commands.NextCommandId(&type)) {
|
||||
switch (type) {
|
||||
case Command::BeginComputePass:
|
||||
{
|
||||
commands.NextCommand<BeginComputePassCmd>();
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::BeginRenderPass:
|
||||
{
|
||||
BeginRenderPassCmd* beginRenderPassCmd = commands.NextCommand<BeginRenderPassCmd>();
|
||||
@ -365,6 +371,12 @@ namespace d3d12 {
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::EndComputePass:
|
||||
{
|
||||
commands.NextCommand<EndComputePassCmd>();
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::EndRenderPass:
|
||||
{
|
||||
EndRenderPassCmd* cmd = commands.NextCommand<EndRenderPassCmd>();
|
||||
|
@ -47,31 +47,35 @@ namespace metal {
|
||||
RenderPass* currentRenderPass = nullptr;
|
||||
Framebuffer* currentFramebuffer = nullptr;
|
||||
|
||||
void FinishEncoders() {
|
||||
void EnsureNoBlitEncoder() {
|
||||
ASSERT(render == nil);
|
||||
ASSERT(compute == nil);
|
||||
if (blit != nil) {
|
||||
[blit endEncoding];
|
||||
blit = nil;
|
||||
}
|
||||
if (compute != nil) {
|
||||
[compute endEncoding];
|
||||
compute = nil;
|
||||
}
|
||||
}
|
||||
|
||||
void EnsureBlit(id<MTLCommandBuffer> commandBuffer) {
|
||||
ASSERT(render == nil);
|
||||
ASSERT(compute == nil);
|
||||
if (blit == nil) {
|
||||
FinishEncoders();
|
||||
blit = [commandBuffer blitCommandEncoder];
|
||||
}
|
||||
}
|
||||
void EnsureCompute(id<MTLCommandBuffer> commandBuffer) {
|
||||
if (compute == nil) {
|
||||
FinishEncoders();
|
||||
compute = [commandBuffer computeCommandEncoder];
|
||||
// TODO(cwallez@chromium.org): does any state need to be reset?
|
||||
}
|
||||
|
||||
void BeginCompute(id<MTLCommandBuffer> commandBuffer) {
|
||||
EnsureNoBlitEncoder();
|
||||
compute = [commandBuffer computeCommandEncoder];
|
||||
// TODO(cwallez@chromium.org): does any state need to be reset?
|
||||
}
|
||||
|
||||
void EndCompute() {
|
||||
ASSERT(compute != nil);
|
||||
[compute endEncoding];
|
||||
compute = nil;
|
||||
}
|
||||
|
||||
void BeginSubpass(id<MTLCommandBuffer> commandBuffer, uint32_t subpass) {
|
||||
ASSERT(currentRenderPass);
|
||||
if (render != nil) {
|
||||
@ -111,7 +115,8 @@ namespace metal {
|
||||
render = [commandBuffer renderCommandEncoderWithDescriptor:descriptor];
|
||||
// TODO(cwallez@chromium.org): does any state need to be reset?
|
||||
}
|
||||
void EndRenderPass() {
|
||||
|
||||
void EndSubpass() {
|
||||
ASSERT(render != nil);
|
||||
[render endEncoding];
|
||||
render = nil;
|
||||
@ -141,12 +146,19 @@ namespace metal {
|
||||
uint32_t currentSubpass = 0;
|
||||
while (commands.NextCommandId(&type)) {
|
||||
switch (type) {
|
||||
case Command::BeginComputePass:
|
||||
{
|
||||
commands.NextCommand<BeginComputePassCmd>();
|
||||
encoders.BeginCompute(commandBuffer);
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::BeginRenderPass:
|
||||
{
|
||||
BeginRenderPassCmd* beginRenderPassCmd = commands.NextCommand<BeginRenderPassCmd>();
|
||||
encoders.currentRenderPass = ToBackend(beginRenderPassCmd->renderPass.Get());
|
||||
encoders.currentFramebuffer = ToBackend(beginRenderPassCmd->framebuffer.Get());
|
||||
encoders.FinishEncoders();
|
||||
encoders.EnsureNoBlitEncoder();
|
||||
currentSubpass = 0;
|
||||
}
|
||||
break;
|
||||
@ -243,7 +255,7 @@ namespace metal {
|
||||
case Command::Dispatch:
|
||||
{
|
||||
DispatchCmd* dispatch = commands.NextCommand<DispatchCmd>();
|
||||
encoders.EnsureCompute(commandBuffer);
|
||||
ASSERT(encoders.compute);
|
||||
ASSERT(lastPipeline->IsCompute());
|
||||
|
||||
[encoders.compute dispatchThreadgroups:MTLSizeMake(dispatch->x, dispatch->y, dispatch->z)
|
||||
@ -282,16 +294,23 @@ namespace metal {
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::EndComputePass:
|
||||
{
|
||||
commands.NextCommand<EndComputePassCmd>();
|
||||
encoders.EndCompute();
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::EndRenderPass:
|
||||
{
|
||||
commands.NextCommand<EndRenderPassCmd>();
|
||||
encoders.EndRenderPass();
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::EndRenderSubpass:
|
||||
{
|
||||
commands.NextCommand<EndRenderSubpassCmd>();
|
||||
encoders.EndSubpass();
|
||||
currentSubpass += 1;
|
||||
}
|
||||
break;
|
||||
@ -302,7 +321,7 @@ namespace metal {
|
||||
lastPipeline = ToBackend(cmd->pipeline).Get();
|
||||
|
||||
if (lastPipeline->IsCompute()) {
|
||||
encoders.EnsureCompute(commandBuffer);
|
||||
ASSERT(encoders.compute);
|
||||
lastPipeline->Encode(encoders.compute);
|
||||
} else {
|
||||
ASSERT(encoders.render);
|
||||
@ -340,7 +359,7 @@ namespace metal {
|
||||
const auto& layout = group->GetLayout()->GetBindingInfo();
|
||||
|
||||
if (lastPipeline->IsCompute()) {
|
||||
encoders.EnsureCompute(commandBuffer);
|
||||
ASSERT(encoders.compute);
|
||||
} else {
|
||||
ASSERT(encoders.render);
|
||||
}
|
||||
@ -501,7 +520,9 @@ namespace metal {
|
||||
}
|
||||
}
|
||||
|
||||
encoders.FinishEncoders();
|
||||
encoders.EnsureNoBlitEncoder();
|
||||
ASSERT(encoders.render == nil);
|
||||
ASSERT(encoders.compute == nil);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -65,6 +65,12 @@ namespace opengl {
|
||||
|
||||
while(commands.NextCommandId(&type)) {
|
||||
switch (type) {
|
||||
case Command::BeginComputePass:
|
||||
{
|
||||
commands.NextCommand<BeginComputePassCmd>();
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::BeginRenderPass:
|
||||
{
|
||||
commands.NextCommand<BeginRenderPassCmd>();
|
||||
@ -166,6 +172,12 @@ namespace opengl {
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::EndComputePass:
|
||||
{
|
||||
commands.NextCommand<EndComputePassCmd>();
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::EndRenderPass:
|
||||
{
|
||||
commands.NextCommand<EndRenderPassCmd>();
|
||||
|
Loading…
x
Reference in New Issue
Block a user