vendor dependencies, make some changes to how input is done
This commit is contained in:
Generated
Vendored
+54
@@ -0,0 +1,54 @@
|
||||
// Copyright 2022 The Ebiten Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build 386 || arm
|
||||
|
||||
package directx
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type _D3D12_DEPTH_STENCIL_VIEW_DESC struct {
|
||||
Format _DXGI_FORMAT
|
||||
ViewDimension _D3D12_DSV_DIMENSION
|
||||
Flags _D3D12_DSV_FLAGS
|
||||
Texture2D _D3D12_TEX2D_DSV // Union
|
||||
_ [12 - unsafe.Sizeof(_D3D12_TEX2D_DSV{})]byte // Padding for union
|
||||
}
|
||||
|
||||
type _D3D12_RESOURCE_DESC struct {
|
||||
Dimension _D3D12_RESOURCE_DIMENSION
|
||||
_ [4]byte // Padding
|
||||
Alignment uint64
|
||||
Width uint64
|
||||
Height uint32
|
||||
DepthOrArraySize uint16
|
||||
MipLevels uint16
|
||||
Format _DXGI_FORMAT
|
||||
SampleDesc _DXGI_SAMPLE_DESC
|
||||
Layout _D3D12_TEXTURE_LAYOUT
|
||||
Flags _D3D12_RESOURCE_FLAGS
|
||||
|
||||
// This is a pseudo padding which D3D12_RESOURCE_DESC1 would use.
|
||||
// Mysteriously, some functions don't work correctly without this hack (#2867).
|
||||
_ [12]byte
|
||||
}
|
||||
|
||||
type _D3D12_ROOT_PARAMETER struct {
|
||||
ParameterType _D3D12_ROOT_PARAMETER_TYPE
|
||||
DescriptorTable _D3D12_ROOT_DESCRIPTOR_TABLE // Union
|
||||
_ [4]byte // Padding
|
||||
ShaderVisibility _D3D12_SHADER_VISIBILITY
|
||||
}
|
||||
Generated
Vendored
+49
@@ -0,0 +1,49 @@
|
||||
// Copyright 2022 The Ebiten Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build amd64 || arm64
|
||||
|
||||
package directx
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type _D3D12_DEPTH_STENCIL_VIEW_DESC struct {
|
||||
Format _DXGI_FORMAT
|
||||
ViewDimension _D3D12_DSV_DIMENSION
|
||||
Flags _D3D12_DSV_FLAGS
|
||||
_ [4]byte // Padding
|
||||
Texture2D _D3D12_TEX2D_DSV // Union
|
||||
_ [12 - unsafe.Sizeof(_D3D12_TEX2D_DSV{})]byte // Padding for union
|
||||
}
|
||||
|
||||
type _D3D12_RESOURCE_DESC struct {
|
||||
Dimension _D3D12_RESOURCE_DIMENSION
|
||||
Alignment uint64
|
||||
Width uint64
|
||||
Height uint32
|
||||
DepthOrArraySize uint16
|
||||
MipLevels uint16
|
||||
Format _DXGI_FORMAT
|
||||
SampleDesc _DXGI_SAMPLE_DESC
|
||||
Layout _D3D12_TEXTURE_LAYOUT
|
||||
Flags _D3D12_RESOURCE_FLAGS
|
||||
}
|
||||
|
||||
type _D3D12_ROOT_PARAMETER struct {
|
||||
ParameterType _D3D12_ROOT_PARAMETER_TYPE
|
||||
DescriptorTable _D3D12_ROOT_DESCRIPTOR_TABLE // Union
|
||||
ShaderVisibility _D3D12_SHADER_VISIBILITY
|
||||
}
|
||||
Generated
Vendored
+228
@@ -0,0 +1,228 @@
|
||||
// Copyright 2022 The Ebitengine Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build microsoftgdk
|
||||
|
||||
package directx
|
||||
|
||||
// Some functions of ID3D12GraphicsCommandList has additional logics besides the original COM function call.
|
||||
// Then, instead of calling them by LazyProc.Call, we have to defer this call to the C++ side.
|
||||
// These functions are chosen based on the DirectX header file's implementation.
|
||||
//
|
||||
// These functions should be defined on the C++ side like this:
|
||||
//
|
||||
// extern "C" {
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_ClearDepthStencilView(void* i, uintptr_t depthStencilView, int32_t clearFlags, float depth, uint8_t stencil, uint32_t numRects, void* pRects) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->ClearDepthStencilView(D3D12_CPU_DESCRIPTOR_HANDLE{ depthStencilView }, static_cast<D3D12_CLEAR_FLAGS>(clearFlags), depth, stencil, numRects, static_cast<D3D12_RECT*>(pRects));
|
||||
// }
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_ClearRenderTargetView(void* i, uintptr_t pRenderTargetView, void* colorRGBA, uint32_t numRects, void* pRects) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->ClearRenderTargetView(D3D12_CPU_DESCRIPTOR_HANDLE{ pRenderTargetView }, static_cast<FLOAT*>(colorRGBA), numRects, static_cast<D3D12_RECT*>(pRects));
|
||||
// }
|
||||
// uintptr_t Ebitengine_ID3D12GraphicsCommandList_Close(void* i) {
|
||||
// auto r = static_cast<ID3D12GraphicsCommandList*>(i)->Close();
|
||||
// return uintptr_t(r);
|
||||
// }
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_CopyTextureRegion(void* i, void* pDst, uint32_t dstX, uint32_t dstY, uint32_t dstZ, void* pSrc, void* pSrcBox) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->CopyTextureRegion(static_cast<D3D12_TEXTURE_COPY_LOCATION*>(pDst), dstX, dstY, dstZ, static_cast<D3D12_TEXTURE_COPY_LOCATION*>(pSrc), static_cast<D3D12_BOX*>(pSrcBox));
|
||||
// }
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_DrawIndexedInstanced(void* i, uint32_t indexCountPerInstance, uint32_t instanceCount, uint32_t startIndexLocation, int32_t baseVertexLocation, uint32_t startInstanceLocation) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->DrawIndexedInstanced(indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation);
|
||||
// }
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_IASetIndexBuffer(void* i, void* pView) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->IASetIndexBuffer(static_cast<D3D12_INDEX_BUFFER_VIEW*>(pView));
|
||||
// }
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_IASetPrimitiveTopology(void* i, int32_t primitiveTopology) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->IASetPrimitiveTopology(static_cast<D3D12_PRIMITIVE_TOPOLOGY>(primitiveTopology));
|
||||
// }
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_IASetVertexBuffers(void* i, uint32_t startSlot, uint32_t numViews, void* pViews) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->IASetVertexBuffers(startSlot, numViews, static_cast<D3D12_VERTEX_BUFFER_VIEW*>(pViews));
|
||||
// }
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_OMSetRenderTargets(void* i, uint32_t numRenderTargetDescriptors, void* pRenderTargetDescriptors, int rtsSingleHandleToDescriptorRange, void* pDepthStencilDescriptor) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->OMSetRenderTargets(numRenderTargetDescriptors, static_cast<D3D12_CPU_DESCRIPTOR_HANDLE*>(pRenderTargetDescriptors), static_cast<BOOL>(rtsSingleHandleToDescriptorRange), static_cast<D3D12_CPU_DESCRIPTOR_HANDLE*>(pDepthStencilDescriptor));
|
||||
// }
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_OMSetStencilRef(void* i, uint32_t stencilRef) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->OMSetStencilRef(stencilRef);
|
||||
// }
|
||||
// uint32_t Ebitengine_ID3D12GraphicsCommandList_Release(void* i) {
|
||||
// return static_cast<uint32_t>(static_cast<ID3D12GraphicsCommandList*>(i)->Release());
|
||||
// }
|
||||
// uintptr_t Ebitengine_ID3D12GraphicsCommandList_Reset(void* i, void* pAllocator, void* pInitialState) {
|
||||
// auto r = static_cast<ID3D12GraphicsCommandList*>(i)->Reset(static_cast<ID3D12CommandAllocator*>(pAllocator), static_cast<ID3D12PipelineState*>(pInitialState));
|
||||
// return static_cast<uintptr_t>(r);
|
||||
// }
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_ResourceBarrier(void* i, uint32_t numBarriers, void* pBarriers) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->ResourceBarrier(numBarriers, static_cast<D3D12_RESOURCE_BARRIER*>(pBarriers));
|
||||
// }
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_RSSetViewports(void* i, uint32_t numViewports, void* pViewports) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->RSSetViewports(numViewports, static_cast<D3D12_VIEWPORT*>(pViewports));
|
||||
// }
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_RSSetScissorRects(void* i, uint32_t numRects, void* pRects) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->RSSetScissorRects(numRects, static_cast<D3D12_RECT*>(pRects));
|
||||
// }
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_SetDescriptorHeaps(void* i, uint32_t numDescriptorHeaps, void* ppDescriptorHeaps) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->SetDescriptorHeaps(numDescriptorHeaps, static_cast<ID3D12DescriptorHeap**>(ppDescriptorHeaps));
|
||||
// }
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(void* i, uint32_t rootParameterIndex, uint64_t baseDescriptorPtr) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->SetGraphicsRootDescriptorTable(rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE{ baseDescriptorPtr });
|
||||
// }
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_SetGraphicsRootSignature(void* i, void* pRootSignature) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->SetGraphicsRootSignature(static_cast<ID3D12RootSignature*>(pRootSignature));
|
||||
// }
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_SetPipelineState(void* i, void* pPipelineState) {
|
||||
// static_cast<ID3D12GraphicsCommandList*>(i)->SetPipelineState(static_cast<ID3D12PipelineState*>(pPipelineState));
|
||||
// }
|
||||
// }
|
||||
|
||||
// #include <stdint.h>
|
||||
//
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_ClearDepthStencilView(void* i, uintptr_t depthStencilView, int32_t clearFlags, float depth, uint8_t stencil, uint32_t numRects, void* pRects);
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_ClearRenderTargetView(void* i, uintptr_t pRenderTargetView, void* colorRGBA, uint32_t numRects, void* pRects);
|
||||
// uintptr_t Ebitengine_ID3D12GraphicsCommandList_Close(void* i);
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_CopyTextureRegion(void* i, void* pDst, uint32_t dstX, uint32_t dstY, uint32_t dstZ, void* pSrc, void* pSrcBox);
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_DrawIndexedInstanced(void* i, uint32_t indexCountPerInstance, uint32_t instanceCount, uint32_t startIndexLocation, int32_t baseVertexLocation, uint32_t startInstanceLocation);
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_IASetIndexBuffer(void* i, void* pView);
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_IASetPrimitiveTopology(void* i, int32_t primitiveTopology);
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_IASetVertexBuffers(void* i, uint32_t startSlot, uint32_t numViews, void* pViews);
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_OMSetRenderTargets(void* i, uint32_t numRenderTargetDescriptors, void* pRenderTargetDescriptors, int rtsSingleHandleToDescriptorRange, void* pDepthStencilDescriptor);
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_OMSetStencilRef(void* i, uint32_t stencilRef);
|
||||
// uint32_t Ebitengine_ID3D12GraphicsCommandList_Release(void* i);
|
||||
// uintptr_t Ebitengine_ID3D12GraphicsCommandList_Reset(void* i, void* pAllocator, void* pInitialState);
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_ResourceBarrier(void* i, uint32_t numBarriers, void* pBarriers);
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_RSSetViewports(void* i, uint32_t numViewports, void* pViewports);
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_RSSetScissorRects(void* i, uint32_t numRects, void* pRects);
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_SetDescriptorHeaps(void* i, uint32_t numDescriptorHeaps, void* ppDescriptorHeaps);
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(void* i, uint32_t rootParameterIndex, uint64_t baseDescriptorPtr);
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_SetGraphicsRootSignature(void* i, void* pRootSignature);
|
||||
// void Ebitengine_ID3D12GraphicsCommandList_SetPipelineState(void* i, void* pPipelineState);
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func _ID3D12GraphicsCommandList_ClearDepthStencilView(i *_ID3D12GraphicsCommandList, depthStencilView _D3D12_CPU_DESCRIPTOR_HANDLE, clearFlags _D3D12_CLEAR_FLAGS, depth float32, stencil uint8, rects []_D3D12_RECT) {
|
||||
var pRects *_D3D12_RECT
|
||||
if len(rects) > 0 {
|
||||
pRects = &rects[0]
|
||||
}
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_ClearDepthStencilView(unsafe.Pointer(i), C.uintptr_t(depthStencilView.ptr), C.int32_t(clearFlags), C.float(depth), C.uint8_t(stencil), C.uint32_t(len(rects)), unsafe.Pointer(pRects))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_ClearRenderTargetView(i *_ID3D12GraphicsCommandList, pRenderTargetView _D3D12_CPU_DESCRIPTOR_HANDLE, colorRGBA [4]float32, rects []_D3D12_RECT) {
|
||||
var pRects *_D3D12_RECT
|
||||
if len(rects) > 0 {
|
||||
pRects = &rects[0]
|
||||
}
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_ClearRenderTargetView(unsafe.Pointer(i), C.uintptr_t(pRenderTargetView.ptr), unsafe.Pointer(&colorRGBA[0]), C.uint32_t(len(rects)), unsafe.Pointer(pRects))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_Close(i *_ID3D12GraphicsCommandList) uintptr {
|
||||
r := C.Ebitengine_ID3D12GraphicsCommandList_Close(unsafe.Pointer(i))
|
||||
return uintptr(r)
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_CopyTextureRegion(i *_ID3D12GraphicsCommandList, pDst unsafe.Pointer, dstX uint32, dstY uint32, dstZ uint32, pSrc unsafe.Pointer, pSrcBox *_D3D12_BOX) {
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_CopyTextureRegion(unsafe.Pointer(i), pDst, C.uint32_t(dstX), C.uint32_t(dstY), C.uint32_t(dstZ), pSrc, unsafe.Pointer(pSrcBox))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_DrawIndexedInstanced(i *_ID3D12GraphicsCommandList, indexCountPerInstance uint32, instanceCount uint32, startIndexLocation uint32, baseVertexLocation int32, startInstanceLocation uint32) {
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_DrawIndexedInstanced(unsafe.Pointer(i),
|
||||
C.uint32_t(indexCountPerInstance), C.uint32_t(instanceCount), C.uint32_t(startIndexLocation),
|
||||
C.int32_t(baseVertexLocation), C.uint32_t(startInstanceLocation))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_IASetIndexBuffer(i *_ID3D12GraphicsCommandList, pView *_D3D12_INDEX_BUFFER_VIEW) {
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_IASetIndexBuffer(unsafe.Pointer(i), unsafe.Pointer(pView))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_IASetPrimitiveTopology(i *_ID3D12GraphicsCommandList, primitiveTopology _D3D_PRIMITIVE_TOPOLOGY) {
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_IASetPrimitiveTopology(unsafe.Pointer(i), C.int32_t(primitiveTopology))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_IASetVertexBuffers(i *_ID3D12GraphicsCommandList, startSlot uint32, views []_D3D12_VERTEX_BUFFER_VIEW) {
|
||||
var pViews *_D3D12_VERTEX_BUFFER_VIEW
|
||||
if len(views) > 0 {
|
||||
pViews = &views[0]
|
||||
}
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_IASetVertexBuffers(unsafe.Pointer(i), C.uint32_t(startSlot), C.uint32_t(len(views)), unsafe.Pointer(pViews))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_OMSetRenderTargets(i *_ID3D12GraphicsCommandList, renderTargetDescriptors []_D3D12_CPU_DESCRIPTOR_HANDLE, rtsSingleHandleToDescriptorRange bool, pDepthStencilDescriptor *_D3D12_CPU_DESCRIPTOR_HANDLE) {
|
||||
var pRenderTargetDescriptors *_D3D12_CPU_DESCRIPTOR_HANDLE
|
||||
if len(renderTargetDescriptors) > 0 {
|
||||
pRenderTargetDescriptors = &renderTargetDescriptors[0]
|
||||
}
|
||||
v := 0
|
||||
if rtsSingleHandleToDescriptorRange {
|
||||
v = 1
|
||||
}
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_OMSetRenderTargets(unsafe.Pointer(i), C.uint32_t(len(renderTargetDescriptors)), unsafe.Pointer(pRenderTargetDescriptors), C.int(v), unsafe.Pointer(pDepthStencilDescriptor))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_OMSetStencilRef(i *_ID3D12GraphicsCommandList, stencilRef uint32) {
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_OMSetStencilRef(unsafe.Pointer(i), C.uint32_t(stencilRef))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_Release(i *_ID3D12GraphicsCommandList) uint32 {
|
||||
return uint32(C.Ebitengine_ID3D12GraphicsCommandList_Release(unsafe.Pointer(i)))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_Reset(i *_ID3D12GraphicsCommandList, pAllocator *_ID3D12CommandAllocator, pInitialState *_ID3D12PipelineState) uintptr {
|
||||
r := C.Ebitengine_ID3D12GraphicsCommandList_Reset(unsafe.Pointer(i), unsafe.Pointer(pAllocator), unsafe.Pointer(pInitialState))
|
||||
return uintptr(r)
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_ResourceBarrier(i *_ID3D12GraphicsCommandList, barriers []_D3D12_RESOURCE_BARRIER_Transition) {
|
||||
var pBarriers *_D3D12_RESOURCE_BARRIER_Transition
|
||||
if len(barriers) > 0 {
|
||||
pBarriers = &barriers[0]
|
||||
}
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_ResourceBarrier(unsafe.Pointer(i), C.uint32_t(len(barriers)), unsafe.Pointer(pBarriers))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_RSSetViewports(i *_ID3D12GraphicsCommandList, viewports []_D3D12_VIEWPORT) {
|
||||
var pViewports *_D3D12_VIEWPORT
|
||||
if len(viewports) > 0 {
|
||||
pViewports = &viewports[0]
|
||||
}
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_RSSetViewports(unsafe.Pointer(i), C.uint32_t(len(viewports)), unsafe.Pointer(pViewports))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_RSSetScissorRects(i *_ID3D12GraphicsCommandList, rects []_D3D12_RECT) {
|
||||
var pRects *_D3D12_RECT
|
||||
if len(rects) > 0 {
|
||||
pRects = &rects[0]
|
||||
}
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_RSSetScissorRects(unsafe.Pointer(i), C.uint32_t(len(rects)), unsafe.Pointer(pRects))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_SetDescriptorHeaps(i *_ID3D12GraphicsCommandList, descriptorHeaps []*_ID3D12DescriptorHeap) {
|
||||
var ppDescriptorHeaps **_ID3D12DescriptorHeap
|
||||
if len(descriptorHeaps) > 0 {
|
||||
ppDescriptorHeaps = &descriptorHeaps[0]
|
||||
}
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_SetDescriptorHeaps(unsafe.Pointer(i), C.uint32_t(len(descriptorHeaps)), unsafe.Pointer(ppDescriptorHeaps))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(i *_ID3D12GraphicsCommandList, rootParameterIndex uint32, baseDescriptor _D3D12_GPU_DESCRIPTOR_HANDLE) {
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(unsafe.Pointer(i), C.uint32_t(rootParameterIndex), C.uint64_t(baseDescriptor.ptr))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_SetGraphicsRootSignature(i *_ID3D12GraphicsCommandList, pRootSignature *_ID3D12RootSignature) {
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_SetGraphicsRootSignature(unsafe.Pointer(i), unsafe.Pointer(pRootSignature))
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_SetPipelineState(i *_ID3D12GraphicsCommandList, pPipelineState *_ID3D12PipelineState) {
|
||||
C.Ebitengine_ID3D12GraphicsCommandList_SetPipelineState(unsafe.Pointer(i), unsafe.Pointer(pPipelineState))
|
||||
}
|
||||
Generated
Vendored
+97
@@ -0,0 +1,97 @@
|
||||
// Copyright 2022 The Ebitengine Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !microsoftgdk
|
||||
|
||||
package directx
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func _ID3D12GraphicsCommandList_ClearDepthStencilView(i *_ID3D12GraphicsCommandList, depthStencilView _D3D12_CPU_DESCRIPTOR_HANDLE, clearFlags _D3D12_CLEAR_FLAGS, depth float32, stencil uint8, rects []_D3D12_RECT) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_ClearRenderTargetView(i *_ID3D12GraphicsCommandList, pRenderTargetView _D3D12_CPU_DESCRIPTOR_HANDLE, colorRGBA [4]float32, rects []_D3D12_RECT) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_Close(i *_ID3D12GraphicsCommandList) uintptr {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_CopyTextureRegion(i *_ID3D12GraphicsCommandList, pDst unsafe.Pointer, dstX uint32, dstY uint32, dstZ uint32, pSrc unsafe.Pointer, pSrcBox *_D3D12_BOX) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_DrawIndexedInstanced(i *_ID3D12GraphicsCommandList, indexCountPerInstance uint32, instanceCount uint32, startIndexLocation uint32, baseVertexLocation int32, startInstanceLocation uint32) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_IASetIndexBuffer(i *_ID3D12GraphicsCommandList, pView *_D3D12_INDEX_BUFFER_VIEW) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_IASetPrimitiveTopology(i *_ID3D12GraphicsCommandList, primitiveTopology _D3D_PRIMITIVE_TOPOLOGY) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_IASetVertexBuffers(i *_ID3D12GraphicsCommandList, startSlot uint32, pViews []_D3D12_VERTEX_BUFFER_VIEW) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_OMSetRenderTargets(i *_ID3D12GraphicsCommandList, renderTargetDescriptors []_D3D12_CPU_DESCRIPTOR_HANDLE, rtsSingleHandleToDescriptorRange bool, pDepthStencilDescriptor *_D3D12_CPU_DESCRIPTOR_HANDLE) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_OMSetStencilRef(i *_ID3D12GraphicsCommandList, stencilRef uint32) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_Release(i *_ID3D12GraphicsCommandList) uint32 {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_Reset(i *_ID3D12GraphicsCommandList, pAllocator *_ID3D12CommandAllocator, pInitialState *_ID3D12PipelineState) uintptr {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_ResourceBarrier(i *_ID3D12GraphicsCommandList, barriers []_D3D12_RESOURCE_BARRIER_Transition) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_RSSetViewports(i *_ID3D12GraphicsCommandList, viewports []_D3D12_VIEWPORT) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_RSSetScissorRects(i *_ID3D12GraphicsCommandList, rects []_D3D12_RECT) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_SetDescriptorHeaps(i *_ID3D12GraphicsCommandList, descriptorHeaps []*_ID3D12DescriptorHeap) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(i *_ID3D12GraphicsCommandList, rootParameterIndex uint32, baseDescriptor _D3D12_GPU_DESCRIPTOR_HANDLE) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_SetGraphicsRootSignature(i *_ID3D12GraphicsCommandList, pRootSignature *_ID3D12RootSignature) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func _ID3D12GraphicsCommandList_SetPipelineState(i *_ID3D12GraphicsCommandList, pPipelineState *_ID3D12PipelineState) {
|
||||
panic("not implemented")
|
||||
}
|
||||
Generated
Vendored
+60
@@ -0,0 +1,60 @@
|
||||
// Copyright 2022 The Ebiten Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package directx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const is64bit = unsafe.Sizeof(uintptr(0)) == 8
|
||||
|
||||
type handleError windows.Handle
|
||||
|
||||
func (h handleError) Error() string {
|
||||
return fmt.Sprintf("HANDLE(%d)", h)
|
||||
}
|
||||
|
||||
type (
|
||||
_BOOL int32
|
||||
)
|
||||
|
||||
func boolToUintptr(v bool) uintptr {
|
||||
if v {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type _PAPPSTATE_CHANGE_ROUTINE func(quiesced bool, context unsafe.Pointer) uintptr
|
||||
|
||||
var (
|
||||
// https://github.com/MicrosoftDocs/sdk-api/blob/docs/sdk-api-src/content/appnotify/nf-appnotify-registerappstatechangenotification.md
|
||||
appnotify = windows.NewLazySystemDLL("API-MS-Win-Core-psm-appnotify-l1-1-0.dll")
|
||||
|
||||
procRegisterAppStateChangeNotification = appnotify.NewProc("RegisterAppStateChangeNotification")
|
||||
)
|
||||
|
||||
func _RegisterAppStateChangeNotification(routine _PAPPSTATE_CHANGE_ROUTINE, context unsafe.Pointer) (unsafe.Pointer, error) {
|
||||
cb := windows.NewCallback(routine)
|
||||
var registration unsafe.Pointer
|
||||
r, _, _ := procRegisterAppStateChangeNotification.Call(cb, uintptr(context), uintptr(unsafe.Pointer(®istration)))
|
||||
if windows.Errno(r) != windows.ERROR_SUCCESS {
|
||||
return nil, fmt.Errorf("directx: RegisterAppStateChangeNotification failed: %w", windows.Errno(r))
|
||||
}
|
||||
return registration, nil
|
||||
}
|
||||
Generated
Vendored
+1349
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+2077
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+180
@@ -0,0 +1,180 @@
|
||||
// Copyright 2023 The Ebitengine Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package directx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// Reference:
|
||||
// * https://github.com/wine-mirror/wine/blob/master/include/d3dcommon.idl
|
||||
|
||||
type _D3DCOMPILE uint32
|
||||
|
||||
const (
|
||||
_D3DCOMPILE_OPTIMIZATION_LEVEL3 _D3DCOMPILE = (1 << 15)
|
||||
)
|
||||
|
||||
type _D3D_DRIVER_TYPE int32
|
||||
|
||||
const (
|
||||
_D3D_DRIVER_TYPE_UNKNOWN _D3D_DRIVER_TYPE = iota
|
||||
_D3D_DRIVER_TYPE_HARDWARE
|
||||
_D3D_DRIVER_TYPE_REFERENCE
|
||||
_D3D_DRIVER_TYPE_NULL
|
||||
_D3D_DRIVER_TYPE_SOFTWARE
|
||||
_D3D_DRIVER_TYPE_WARP
|
||||
)
|
||||
|
||||
type _D3D_FEATURE_LEVEL int32
|
||||
|
||||
const (
|
||||
_D3D_FEATURE_LEVEL_9_1 _D3D_FEATURE_LEVEL = 0x9100
|
||||
_D3D_FEATURE_LEVEL_9_2 _D3D_FEATURE_LEVEL = 0x9200
|
||||
_D3D_FEATURE_LEVEL_9_3 _D3D_FEATURE_LEVEL = 0x9300
|
||||
_D3D_FEATURE_LEVEL_10_0 _D3D_FEATURE_LEVEL = 0xa000
|
||||
_D3D_FEATURE_LEVEL_10_1 _D3D_FEATURE_LEVEL = 0xa100
|
||||
_D3D_FEATURE_LEVEL_11_0 _D3D_FEATURE_LEVEL = 0xb000
|
||||
_D3D_FEATURE_LEVEL_11_1 _D3D_FEATURE_LEVEL = 0xb100
|
||||
_D3D_FEATURE_LEVEL_12_0 _D3D_FEATURE_LEVEL = 0xc000
|
||||
_D3D_FEATURE_LEVEL_12_1 _D3D_FEATURE_LEVEL = 0xc100
|
||||
_D3D_FEATURE_LEVEL_12_2 _D3D_FEATURE_LEVEL = 0xc200
|
||||
)
|
||||
|
||||
type _D3D_PRIMITIVE_TOPOLOGY int32
|
||||
|
||||
const (
|
||||
_D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST _D3D_PRIMITIVE_TOPOLOGY = 4
|
||||
)
|
||||
|
||||
type _D3D_ROOT_SIGNATURE_VERSION int32
|
||||
|
||||
const (
|
||||
_D3D_ROOT_SIGNATURE_VERSION_1_0 _D3D_ROOT_SIGNATURE_VERSION = 0x1
|
||||
)
|
||||
|
||||
var (
|
||||
procD3DCompile *windows.LazyProc
|
||||
)
|
||||
|
||||
func init() {
|
||||
var d3dcompiler *windows.LazyDLL
|
||||
|
||||
// Enumerate possible DLL names for d3dcompiler_*.dll.
|
||||
// https://walbourn.github.io/hlsl-fxc-and-d3dcompile/
|
||||
for _, name := range []string{"d3dcompiler_47.dll", "d3dcompiler_46.dll", "d3dcompiler_43.dll"} {
|
||||
dll := windows.NewLazySystemDLL(name)
|
||||
if err := dll.Load(); err != nil {
|
||||
continue
|
||||
}
|
||||
d3dcompiler = dll
|
||||
break
|
||||
}
|
||||
|
||||
if d3dcompiler == nil {
|
||||
return
|
||||
}
|
||||
|
||||
procD3DCompile = d3dcompiler.NewProc("D3DCompile")
|
||||
}
|
||||
|
||||
func isD3DCompilerDLLAvailable() bool {
|
||||
return procD3DCompile != nil
|
||||
}
|
||||
|
||||
func _D3DCompile(srcData []byte, sourceName string, pDefines []_D3D_SHADER_MACRO, pInclude unsafe.Pointer, entryPoint string, target string, flags1 uint32, flags2 uint32) (*_ID3DBlob, error) {
|
||||
if !isD3DCompilerDLLAvailable() {
|
||||
return nil, fmt.Errorf("directx: d3dcompiler_*.dll is missing in this environment")
|
||||
}
|
||||
|
||||
// TODO: Define _ID3DInclude for pInclude, but is it possible in Go?
|
||||
|
||||
var defs unsafe.Pointer
|
||||
if len(pDefines) > 0 {
|
||||
defs = unsafe.Pointer(&pDefines[0])
|
||||
}
|
||||
sourceNameBytes := append([]byte(sourceName), 0)
|
||||
entryPointBytes := append([]byte(entryPoint), 0)
|
||||
targetBytes := append([]byte(target), 0)
|
||||
var code *_ID3DBlob
|
||||
var errorMsgs *_ID3DBlob
|
||||
r, _, _ := procD3DCompile.Call(
|
||||
uintptr(unsafe.Pointer(&srcData[0])), uintptr(len(srcData)), uintptr(unsafe.Pointer(&sourceNameBytes[0])),
|
||||
uintptr(defs), uintptr(unsafe.Pointer(pInclude)), uintptr(unsafe.Pointer(&entryPointBytes[0])),
|
||||
uintptr(unsafe.Pointer(&targetBytes[0])), uintptr(flags1), uintptr(flags2),
|
||||
uintptr(unsafe.Pointer(&code)), uintptr(unsafe.Pointer(&errorMsgs)))
|
||||
runtime.KeepAlive(pDefines)
|
||||
runtime.KeepAlive(pInclude)
|
||||
runtime.KeepAlive(sourceNameBytes)
|
||||
runtime.KeepAlive(entryPointBytes)
|
||||
runtime.KeepAlive(targetBytes)
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
if errorMsgs != nil {
|
||||
defer errorMsgs.Release()
|
||||
return nil, fmt.Errorf("directx: D3DCompile failed: %s: %w", errorMsgs.String(), handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return nil, fmt.Errorf("directx: D3DCompile failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return code, nil
|
||||
}
|
||||
|
||||
type _D3D_SHADER_MACRO struct {
|
||||
Name *byte
|
||||
Definition *byte
|
||||
}
|
||||
|
||||
type _ID3DBlob struct {
|
||||
vtbl *_ID3DBlob_Vtbl
|
||||
}
|
||||
|
||||
type _ID3DBlob_Vtbl struct {
|
||||
QueryInterface uintptr
|
||||
AddRef uintptr
|
||||
Release uintptr
|
||||
|
||||
GetBufferPointer uintptr
|
||||
GetBufferSize uintptr
|
||||
}
|
||||
|
||||
func (i *_ID3DBlob) AddRef() uint32 {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.AddRef, 1, uintptr(unsafe.Pointer(i)), 0, 0)
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
func (i *_ID3DBlob) GetBufferPointer() unsafe.Pointer {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.GetBufferPointer, 1, uintptr(unsafe.Pointer(i)),
|
||||
0, 0)
|
||||
return unsafe.Pointer(r)
|
||||
}
|
||||
|
||||
func (i *_ID3DBlob) GetBufferSize() uintptr {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.GetBufferSize, 1, uintptr(unsafe.Pointer(i)),
|
||||
0, 0)
|
||||
return r
|
||||
}
|
||||
|
||||
func (i *_ID3DBlob) Release() uint32 {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
func (i *_ID3DBlob) String() string {
|
||||
return string(unsafe.Slice((*byte)(unsafe.Pointer(i.GetBufferPointer())), i.GetBufferSize()))
|
||||
}
|
||||
Generated
Vendored
+622
@@ -0,0 +1,622 @@
|
||||
// Copyright 2023 The Ebitengine Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package directx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type _DXGI_ALPHA_MODE uint32
|
||||
|
||||
const (
|
||||
_DXGI_ALPHA_MODE_UNSPECIFIED _DXGI_ALPHA_MODE = 0
|
||||
_DXGI_ALPHA_MODE_PREMULTIPLIED _DXGI_ALPHA_MODE = 1
|
||||
_DXGI_ALPHA_MODE_STRAIGHT _DXGI_ALPHA_MODE = 2
|
||||
_DXGI_ALPHA_MODE_IGNORE _DXGI_ALPHA_MODE = 3
|
||||
_DXGI_ALPHA_MODE_FORCE_DWORD _DXGI_ALPHA_MODE = 0xffffffff
|
||||
)
|
||||
|
||||
type _DXGI_COLOR_SPACE_TYPE int32
|
||||
|
||||
type _DXGI_FEATURE int32
|
||||
|
||||
const (
|
||||
_DXGI_FEATURE_PRESENT_ALLOW_TEARING _DXGI_FEATURE = 0
|
||||
)
|
||||
|
||||
type _DXGI_FORMAT int32
|
||||
|
||||
const (
|
||||
_DXGI_FORMAT_UNKNOWN _DXGI_FORMAT = 0
|
||||
_DXGI_FORMAT_R32G32B32A32_FLOAT _DXGI_FORMAT = 2
|
||||
_DXGI_FORMAT_R32G32_FLOAT _DXGI_FORMAT = 16
|
||||
_DXGI_FORMAT_R8G8B8A8_UNORM _DXGI_FORMAT = 28
|
||||
_DXGI_FORMAT_R32_UINT _DXGI_FORMAT = 42
|
||||
_DXGI_FORMAT_D24_UNORM_S8_UINT _DXGI_FORMAT = 45
|
||||
_DXGI_FORMAT_B8G8R8A8_UNORM _DXGI_FORMAT = 87
|
||||
)
|
||||
|
||||
type _DXGI_MODE_SCANLINE_ORDER int32
|
||||
|
||||
type _DXGI_MODE_SCALING int32
|
||||
|
||||
type _DXGI_PRESENT uint32
|
||||
|
||||
const (
|
||||
_DXGI_PRESENT_TEST _DXGI_PRESENT = 0x00000001
|
||||
_DXGI_PRESENT_ALLOW_TEARING _DXGI_PRESENT = 0x00000200
|
||||
)
|
||||
|
||||
type _DXGI_SCALING int32
|
||||
|
||||
type _DXGI_SWAP_CHAIN_FLAG int32
|
||||
|
||||
const (
|
||||
_DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING _DXGI_SWAP_CHAIN_FLAG = 2048
|
||||
)
|
||||
|
||||
type _DXGI_SWAP_EFFECT int32
|
||||
|
||||
const (
|
||||
_DXGI_SWAP_EFFECT_DISCARD _DXGI_SWAP_EFFECT = 0
|
||||
_DXGI_SWAP_EFFECT_SEQUENTIAL _DXGI_SWAP_EFFECT = 1
|
||||
_DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL _DXGI_SWAP_EFFECT = 3
|
||||
_DXGI_SWAP_EFFECT_FLIP_DISCARD _DXGI_SWAP_EFFECT = 4
|
||||
)
|
||||
|
||||
type _DXGI_USAGE uint32
|
||||
|
||||
const (
|
||||
_DXGI_USAGE_RENDER_TARGET_OUTPUT _DXGI_USAGE = 1 << (1 + 4)
|
||||
)
|
||||
|
||||
const (
|
||||
_DXGI_ADAPTER_FLAG_SOFTWARE = 2
|
||||
|
||||
_DXGI_CREATE_FACTORY_DEBUG = 0x01
|
||||
|
||||
_DXGI_ERROR_NOT_FOUND = handleError(0x887A0002)
|
||||
|
||||
_DXGI_MWA_NO_ALT_ENTER = 0x2
|
||||
_DXGI_MWA_NO_WINDOW_CHANGES = 0x1
|
||||
)
|
||||
|
||||
var (
|
||||
_IID_IDXGIAdapter1 = windows.GUID{Data1: 0x29038f61, Data2: 0x3839, Data3: 0x4626, Data4: [...]byte{0x91, 0xfd, 0x08, 0x68, 0x79, 0x01, 0x1a, 0x05}}
|
||||
_IID_IDXGIDevice = windows.GUID{Data1: 0x54ec77fa, Data2: 0x1377, Data3: 0x44e6, Data4: [...]byte{0x8c, 0x32, 0x88, 0xfd, 0x5f, 0x44, 0xc8, 0x4c}}
|
||||
_IID_IDXGIFactory = windows.GUID{Data1: 0x7b7166ec, Data2: 0x21c7, Data3: 0x44ae, Data4: [...]byte{0xb2, 0x1a, 0xc9, 0xae, 0x32, 0x1a, 0xe3, 0x69}}
|
||||
_IID_IDXGIFactory4 = windows.GUID{Data1: 0x1bc6ea02, Data2: 0xef36, Data3: 0x464f, Data4: [...]byte{0xbf, 0x0c, 0x21, 0xca, 0x39, 0xe5, 0x16, 0x8a}}
|
||||
_IID_IDXGIFactory5 = windows.GUID{Data1: 0x7632e1f5, Data2: 0xee65, Data3: 0x4dca, Data4: [...]byte{0x87, 0xfd, 0x84, 0xcd, 0x75, 0xf8, 0x83, 0x8d}}
|
||||
_IID_IDXGISwapChain4 = windows.GUID{Data1: 0x3d585d5a, Data2: 0xbd4a, Data3: 0x489e, Data4: [...]byte{0xb1, 0xf4, 0x3d, 0xbc, 0xb6, 0x45, 0x2f, 0xfb}}
|
||||
)
|
||||
|
||||
var (
|
||||
dxgi = windows.NewLazySystemDLL("dxgi.dll")
|
||||
|
||||
procCreateDXGIFactory = dxgi.NewProc("CreateDXGIFactory")
|
||||
)
|
||||
|
||||
func _CreateDXGIFactory() (*_IDXGIFactory, error) {
|
||||
var factory *_IDXGIFactory
|
||||
r, _, _ := procCreateDXGIFactory.Call(uintptr(unsafe.Pointer(&_IID_IDXGIFactory)), uintptr(unsafe.Pointer(&factory)))
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
return nil, fmt.Errorf("directx: CreateDXGIFactory failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return factory, nil
|
||||
}
|
||||
|
||||
type _DXGI_ADAPTER_DESC1 struct {
|
||||
Description [128]uint16
|
||||
VendorId uint32
|
||||
DeviceId uint32
|
||||
SubSysId uint32
|
||||
Revision uint32
|
||||
DedicatedVideoMemory uint
|
||||
DedicatedSystemMemory uint
|
||||
SharedSystemMemory uint
|
||||
AdapterLuid _LUID
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
type _DXGI_MODE_DESC struct {
|
||||
Width uint32
|
||||
Height uint32
|
||||
RefreshRate _DXGI_RATIONAL
|
||||
Format _DXGI_FORMAT
|
||||
ScanlineOrdering _DXGI_MODE_SCANLINE_ORDER
|
||||
Scaling _DXGI_MODE_SCALING
|
||||
}
|
||||
|
||||
type _DXGI_RATIONAL struct {
|
||||
Numerator uint32
|
||||
Denominator uint32
|
||||
}
|
||||
|
||||
type _DXGI_SWAP_CHAIN_FULLSCREEN_DESC struct {
|
||||
RefreshRate _DXGI_RATIONAL
|
||||
ScanlineOrdering _DXGI_MODE_SCANLINE_ORDER
|
||||
Scaling _DXGI_MODE_SCALING
|
||||
Windowed _BOOL
|
||||
}
|
||||
|
||||
type _DXGI_SAMPLE_DESC struct {
|
||||
Count uint32
|
||||
Quality uint32
|
||||
}
|
||||
|
||||
type _DXGI_SWAP_CHAIN_DESC struct {
|
||||
BufferDesc _DXGI_MODE_DESC
|
||||
SampleDesc _DXGI_SAMPLE_DESC
|
||||
BufferUsage _DXGI_USAGE
|
||||
BufferCount uint32
|
||||
OutputWindow windows.HWND
|
||||
Windowed _BOOL
|
||||
SwapEffect _DXGI_SWAP_EFFECT
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
type _LUID struct {
|
||||
LowPart uint32
|
||||
HighPart int32
|
||||
}
|
||||
|
||||
type _IDXGIAdapter struct {
|
||||
vtbl *_IDXGIAdapter1_Vtbl
|
||||
}
|
||||
|
||||
type _IDXGIAdapter_Vtbl struct {
|
||||
QueryInterface uintptr
|
||||
AddRef uintptr
|
||||
Release uintptr
|
||||
|
||||
SetPrivateData uintptr
|
||||
SetPrivateDataInterface uintptr
|
||||
GetPrivateData uintptr
|
||||
GetParent uintptr
|
||||
EnumOutputs uintptr
|
||||
GetDesc uintptr
|
||||
CheckInterfaceSupport uintptr
|
||||
}
|
||||
|
||||
func (i *_IDXGIAdapter) EnumOutputs(output uint32) (*_IDXGIOutput, error) {
|
||||
var pOutput *_IDXGIOutput
|
||||
r, _, _ := syscall.Syscall(i.vtbl.EnumOutputs, 3, uintptr(unsafe.Pointer(i)), uintptr(output), uintptr(unsafe.Pointer(&pOutput)))
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
return nil, fmt.Errorf("directx: IDXGIAdapter::EnumOutputs failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return pOutput, nil
|
||||
}
|
||||
|
||||
func (i *_IDXGIAdapter) GetParent(riid *windows.GUID) (unsafe.Pointer, error) {
|
||||
var v unsafe.Pointer
|
||||
r, _, _ := syscall.Syscall(i.vtbl.GetParent, 3, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(riid)), uintptr(unsafe.Pointer(&v)))
|
||||
runtime.KeepAlive(riid)
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
return nil, fmt.Errorf("directx: IDXGIAdapter::GetParent failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (i *_IDXGIAdapter) Release() uint32 {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
type _IDXGIAdapter1 struct {
|
||||
vtbl *_IDXGIAdapter1_Vtbl
|
||||
}
|
||||
|
||||
type _IDXGIAdapter1_Vtbl struct {
|
||||
QueryInterface uintptr
|
||||
AddRef uintptr
|
||||
Release uintptr
|
||||
|
||||
SetPrivateData uintptr
|
||||
SetPrivateDataInterface uintptr
|
||||
GetPrivateData uintptr
|
||||
GetParent uintptr
|
||||
EnumOutputs uintptr
|
||||
GetDesc uintptr
|
||||
CheckInterfaceSupport uintptr
|
||||
GetDesc1 uintptr
|
||||
}
|
||||
|
||||
func (i *_IDXGIAdapter1) Release() uint32 {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
func (i *_IDXGIAdapter1) GetDesc1() (*_DXGI_ADAPTER_DESC1, error) {
|
||||
var desc _DXGI_ADAPTER_DESC1
|
||||
r, _, _ := syscall.Syscall(i.vtbl.GetDesc1, 2, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&desc)), 0)
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
return nil, fmt.Errorf("directx: IDXGIAdapter1::GetDesc1 failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return &desc, nil
|
||||
}
|
||||
|
||||
type _IDXGIDevice struct {
|
||||
vtbl *_IDXGIDevice_Vtbl
|
||||
}
|
||||
|
||||
type _IDXGIDevice_Vtbl struct {
|
||||
QueryInterface uintptr
|
||||
AddRef uintptr
|
||||
Release uintptr
|
||||
|
||||
SetPrivateData uintptr
|
||||
SetPrivateDataInterface uintptr
|
||||
GetPrivateData uintptr
|
||||
GetParent uintptr
|
||||
GetAdapter uintptr
|
||||
CreateSurface uintptr
|
||||
QueryResourceResidency uintptr
|
||||
SetGPUThreadPriority uintptr
|
||||
GetGPUThreadPriority uintptr
|
||||
}
|
||||
|
||||
func (i *_IDXGIDevice) GetAdapter() (*_IDXGIAdapter, error) {
|
||||
var adapter *_IDXGIAdapter
|
||||
r, _, _ := syscall.Syscall(i.vtbl.GetAdapter, 2, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&adapter)), 0)
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
return nil, fmt.Errorf("directx: IDXGIDevice::GetAdapter failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return adapter, nil
|
||||
}
|
||||
|
||||
func (i *_IDXGIDevice) Release() uint32 {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
type _IDXGIFactory struct {
|
||||
vtbl *_IDXGIFactory_Vtbl
|
||||
}
|
||||
|
||||
type _IDXGIFactory_Vtbl struct {
|
||||
QueryInterface uintptr
|
||||
AddRef uintptr
|
||||
Release uintptr
|
||||
|
||||
SetPrivateData uintptr
|
||||
SetPrivateDataInterface uintptr
|
||||
GetPrivateData uintptr
|
||||
GetParent uintptr
|
||||
EnumAdapters uintptr
|
||||
MakeWindowAssociation uintptr
|
||||
GetWindowAssociation uintptr
|
||||
CreateSwapChain uintptr
|
||||
CreateSoftwareAdapter uintptr
|
||||
}
|
||||
|
||||
func (i *_IDXGIFactory) CreateSwapChain(pDevice unsafe.Pointer, pDesc *_DXGI_SWAP_CHAIN_DESC) (*_IDXGISwapChain, error) {
|
||||
var swapChain *_IDXGISwapChain
|
||||
r, _, _ := syscall.Syscall6(i.vtbl.CreateSwapChain, 4, uintptr(unsafe.Pointer(i)),
|
||||
uintptr(pDevice), uintptr(unsafe.Pointer(pDesc)), uintptr(unsafe.Pointer(&swapChain)),
|
||||
0, 0)
|
||||
runtime.KeepAlive(pDevice)
|
||||
runtime.KeepAlive(pDesc)
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
return nil, fmt.Errorf("directx: IDXGIFactory::CreateSwapChain failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return swapChain, nil
|
||||
}
|
||||
|
||||
func (i *_IDXGIFactory) MakeWindowAssociation(windowHandle windows.HWND, flags uint32) error {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.MakeWindowAssociation, 3, uintptr(unsafe.Pointer(i)), uintptr(windowHandle), uintptr(flags))
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
return fmt.Errorf("directx: IDXGIFactory::MakeWIndowAssociation failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *_IDXGIFactory) QueryInterface(riid *windows.GUID) (unsafe.Pointer, error) {
|
||||
var v unsafe.Pointer
|
||||
r, _, _ := syscall.Syscall(i.vtbl.QueryInterface, 3, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(riid)), uintptr(unsafe.Pointer(&v)))
|
||||
runtime.KeepAlive(riid)
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
return nil, fmt.Errorf("directx: IDXGIFactory::QueryInterface failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (i *_IDXGIFactory) Release() uint32 {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
type _IDXGIFactory4 struct {
|
||||
vtbl *_IDXGIFactory4_Vtbl
|
||||
}
|
||||
|
||||
type _IDXGIFactory4_Vtbl struct {
|
||||
QueryInterface uintptr
|
||||
AddRef uintptr
|
||||
Release uintptr
|
||||
|
||||
SetPrivateData uintptr
|
||||
SetPrivateDataInterface uintptr
|
||||
GetPrivateData uintptr
|
||||
GetParent uintptr
|
||||
EnumAdapters uintptr
|
||||
MakeWindowAssociation uintptr
|
||||
GetWindowAssociation uintptr
|
||||
CreateSwapChain uintptr
|
||||
CreateSoftwareAdapter uintptr
|
||||
EnumAdapters1 uintptr
|
||||
IsCurrent uintptr
|
||||
IsWindowedStereoEnabled uintptr
|
||||
CreateSwapChainForHwnd uintptr
|
||||
CreateSwapChainForCoreWindow uintptr
|
||||
GetSharedResourceAdapterLuid uintptr
|
||||
RegisterStereoStatusWindow uintptr
|
||||
RegisterStereoStatusEvent uintptr
|
||||
UnregisterStereoStatus uintptr
|
||||
RegisterOcclusionStatusWindow uintptr
|
||||
RegisterOcclusionStatusEvent uintptr
|
||||
UnregisterOcclusionStatus uintptr
|
||||
CreateSwapChainForComposition uintptr
|
||||
GetCreationFlags uintptr
|
||||
EnumAdapterByLuid uintptr
|
||||
EnumWarpAdapter uintptr
|
||||
}
|
||||
|
||||
func (i *_IDXGIFactory4) EnumAdapters1(adapter uint32) (*_IDXGIAdapter1, error) {
|
||||
var ptr *_IDXGIAdapter1
|
||||
r, _, _ := syscall.Syscall(i.vtbl.EnumAdapters1, 3, uintptr(unsafe.Pointer(i)), uintptr(adapter), uintptr(unsafe.Pointer(&ptr)))
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
return nil, fmt.Errorf("directx: IDXGIFactory4::EnumAdapters1 failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return ptr, nil
|
||||
}
|
||||
|
||||
func (i *_IDXGIFactory4) EnumWarpAdapter() (*_IDXGIAdapter1, error) {
|
||||
var ptr *_IDXGIAdapter1
|
||||
r, _, _ := syscall.Syscall(i.vtbl.EnumWarpAdapter, 3, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&_IID_IDXGIAdapter1)), uintptr(unsafe.Pointer(&ptr)))
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
return nil, fmt.Errorf("directx: IDXGIFactory4::EnumWarpAdapter failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return ptr, nil
|
||||
}
|
||||
|
||||
func (i *_IDXGIFactory4) Release() uint32 {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
type _IDXGIFactory5 struct {
|
||||
vtbl *_IDXGIFactory5_Vtbl
|
||||
}
|
||||
|
||||
type _IDXGIFactory5_Vtbl struct {
|
||||
QueryInterface uintptr
|
||||
AddRef uintptr
|
||||
Release uintptr
|
||||
|
||||
SetPrivateData uintptr
|
||||
SetPrivateDataInterface uintptr
|
||||
GetPrivateData uintptr
|
||||
GetParent uintptr
|
||||
EnumAdapters uintptr
|
||||
MakeWindowAssociation uintptr
|
||||
GetWindowAssociation uintptr
|
||||
CreateSwapChain uintptr
|
||||
CreateSoftwareAdapter uintptr
|
||||
EnumAdapters1 uintptr
|
||||
IsCurrent uintptr
|
||||
IsWindowedStereoEnabled uintptr
|
||||
CreateSwapChainForHwnd uintptr
|
||||
CreateSwapChainForCoreWindow uintptr
|
||||
GetSharedResourceAdapterLuid uintptr
|
||||
RegisterStereoStatusWindow uintptr
|
||||
RegisterStereoStatusEvent uintptr
|
||||
UnregisterStereoStatus uintptr
|
||||
RegisterOcclusionStatusWindow uintptr
|
||||
RegisterOcclusionStatusEvent uintptr
|
||||
UnregisterOcclusionStatus uintptr
|
||||
CreateSwapChainForComposition uintptr
|
||||
GetCreationFlags uintptr
|
||||
EnumAdapterByLuid uintptr
|
||||
EnumWarpAdapter uintptr
|
||||
CheckFeatureSupport uintptr
|
||||
}
|
||||
|
||||
func (i *_IDXGIFactory5) CheckFeatureSupport(feature _DXGI_FEATURE, pFeatureSupportData unsafe.Pointer, featureSupportDataSize uint32) error {
|
||||
r, _, _ := syscall.Syscall6(i.vtbl.CheckFeatureSupport, 4, uintptr(unsafe.Pointer(i)),
|
||||
uintptr(feature), uintptr(pFeatureSupportData), uintptr(featureSupportDataSize),
|
||||
0, 0)
|
||||
runtime.KeepAlive(pFeatureSupportData)
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
return fmt.Errorf("directx: IDXGIFactory5::CheckFeatureSupport failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *_IDXGIFactory5) Release() uint32 {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
type _IDXGIOutput struct {
|
||||
vtbl *_IDXGIOutput_Vtbl
|
||||
}
|
||||
|
||||
type _IDXGIOutput_Vtbl struct {
|
||||
QueryInterface uintptr
|
||||
AddRef uintptr
|
||||
Release uintptr
|
||||
|
||||
SetPrivateData uintptr
|
||||
SetPrivateDataInterface uintptr
|
||||
GetPrivateData uintptr
|
||||
GetParent uintptr
|
||||
GetDesc uintptr
|
||||
GetDisplayModeList uintptr
|
||||
FindClosestMatchingMode uintptr
|
||||
WaitForVBlank uintptr
|
||||
TakeOwnership uintptr
|
||||
ReleaseOwnership uintptr
|
||||
GetGammaControlCapabilities uintptr
|
||||
SetGammaControl uintptr
|
||||
GetGammaControl uintptr
|
||||
SetDisplaySurface uintptr
|
||||
GetDisplaySurfaceData uintptr
|
||||
GetFrameStatistics uintptr
|
||||
}
|
||||
|
||||
func (i *_IDXGIOutput) Release() uint32 {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
type _IDXGISwapChain struct {
|
||||
vtbl *_IDXGISwapChain_Vtbl
|
||||
}
|
||||
|
||||
type _IDXGISwapChain_Vtbl struct {
|
||||
QueryInterface uintptr
|
||||
AddRef uintptr
|
||||
Release uintptr
|
||||
|
||||
SetPrivateData uintptr
|
||||
SetPrivateDataInterface uintptr
|
||||
GetPrivateData uintptr
|
||||
GetParent uintptr
|
||||
GetDevice uintptr
|
||||
Present uintptr
|
||||
GetBuffer uintptr
|
||||
SetFullscreenState uintptr
|
||||
GetFullscreenState uintptr
|
||||
GetDesc uintptr
|
||||
ResizeBuffers uintptr
|
||||
ResizeTarget uintptr
|
||||
GetContainingOutput uintptr
|
||||
GetFrameStatistics uintptr
|
||||
GetLastPresentCount uintptr
|
||||
}
|
||||
|
||||
func (i *_IDXGISwapChain) GetBuffer(buffer uint32, riid *windows.GUID) (unsafe.Pointer, error) {
|
||||
var resource unsafe.Pointer
|
||||
r, _, _ := syscall.Syscall6(i.vtbl.GetBuffer, 4, uintptr(unsafe.Pointer(i)),
|
||||
uintptr(buffer), uintptr(unsafe.Pointer(riid)), uintptr(unsafe.Pointer(&resource)),
|
||||
0, 0)
|
||||
runtime.KeepAlive(riid)
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
return nil, fmt.Errorf("directx: IDXGISwapChain::GetBuffer failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return resource, nil
|
||||
}
|
||||
|
||||
func (i *_IDXGISwapChain) ResizeBuffers(bufferCount uint32, width uint32, height uint32, newFormat _DXGI_FORMAT, swapChainFlags uint32) error {
|
||||
r, _, _ := syscall.Syscall6(i.vtbl.ResizeBuffers, 6,
|
||||
uintptr(unsafe.Pointer(i)), uintptr(bufferCount), uintptr(width),
|
||||
uintptr(height), uintptr(newFormat), uintptr(swapChainFlags))
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
return fmt.Errorf("directx: IDXGISwapChain::ResizeBuffers failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *_IDXGISwapChain) Present(syncInterval uint32, flags uint32) (occluded bool, err error) {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.Present, 3, uintptr(unsafe.Pointer(i)), uintptr(syncInterval), uintptr(flags))
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
// During a screen lock, Present fails (#2179).
|
||||
if uint32(r) == uint32(windows.DXGI_STATUS_OCCLUDED) {
|
||||
return true, nil
|
||||
}
|
||||
return false, fmt.Errorf("directx: IDXGISwapChain::Present failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (i *_IDXGISwapChain) QueryInterface(riid *windows.GUID) (unsafe.Pointer, error) {
|
||||
var v unsafe.Pointer
|
||||
r, _, _ := syscall.Syscall(i.vtbl.QueryInterface, 3, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(riid)), uintptr(unsafe.Pointer(&v)))
|
||||
runtime.KeepAlive(riid)
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
return nil, fmt.Errorf("directx: IDXGISwapChain::QueryInterface failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (i *_IDXGISwapChain) Release() uint32 {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
type _IDXGISwapChain4 struct {
|
||||
vtbl *_IDXGISwapChain4_Vtbl
|
||||
}
|
||||
|
||||
type _IDXGISwapChain4_Vtbl struct {
|
||||
QueryInterface uintptr
|
||||
AddRef uintptr
|
||||
Release uintptr
|
||||
|
||||
SetPrivateData uintptr
|
||||
SetPrivateDataInterface uintptr
|
||||
GetPrivateData uintptr
|
||||
GetParent uintptr
|
||||
GetDevice uintptr
|
||||
Present uintptr
|
||||
GetBuffer uintptr
|
||||
SetFullscreenState uintptr
|
||||
GetFullscreenState uintptr
|
||||
GetDesc uintptr
|
||||
ResizeBuffers uintptr
|
||||
ResizeTarget uintptr
|
||||
GetContainingOutput uintptr
|
||||
GetFrameStatistics uintptr
|
||||
GetLastPresentCount uintptr
|
||||
GetDesc1 uintptr
|
||||
GetFullscreenDesc uintptr
|
||||
GetHwnd uintptr
|
||||
GetCoreWindow uintptr
|
||||
Present1 uintptr
|
||||
IsTemporaryMonoSupported uintptr
|
||||
GetRestrictToOutput uintptr
|
||||
SetBackgroundColor uintptr
|
||||
GetBackgroundColor uintptr
|
||||
SetRotation uintptr
|
||||
GetRotation uintptr
|
||||
|
||||
SetSourceSize uintptr
|
||||
GetSourceSize uintptr
|
||||
SetMaximumFrameLatency uintptr
|
||||
GetMaximumFrameLatency uintptr
|
||||
GetFrameLatencyWaitableObject uintptr
|
||||
SetMatrixTransform uintptr
|
||||
GetMatrixTransform uintptr
|
||||
GetCurrentBackBufferIndex uintptr
|
||||
CheckColorSpaceSupport uintptr
|
||||
SetColorSpace1 uintptr
|
||||
ResizeBuffers1 uintptr
|
||||
SetHDRMetaData uintptr
|
||||
}
|
||||
|
||||
func (i *_IDXGISwapChain4) GetCurrentBackBufferIndex() uint32 {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.GetCurrentBackBufferIndex, 1, uintptr(unsafe.Pointer(i)), 0, 0)
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
func (i *_IDXGISwapChain4) Release() uint32 {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
|
||||
return uint32(r)
|
||||
}
|
||||
Generated
Vendored
+730
@@ -0,0 +1,730 @@
|
||||
// Copyright 2023 The Ebitengine Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package directx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir/hlsl"
|
||||
)
|
||||
|
||||
var inputElementDescsForDX11 = []_D3D11_INPUT_ELEMENT_DESC{
|
||||
{
|
||||
SemanticName: &([]byte("POSITION\000"))[0],
|
||||
SemanticIndex: 0,
|
||||
Format: _DXGI_FORMAT_R32G32_FLOAT,
|
||||
InputSlot: 0,
|
||||
AlignedByteOffset: _D3D11_APPEND_ALIGNED_ELEMENT,
|
||||
InputSlotClass: _D3D11_INPUT_PER_VERTEX_DATA,
|
||||
InstanceDataStepRate: 0,
|
||||
},
|
||||
{
|
||||
SemanticName: &([]byte("TEXCOORD\000"))[0],
|
||||
SemanticIndex: 0,
|
||||
Format: _DXGI_FORMAT_R32G32_FLOAT,
|
||||
InputSlot: 0,
|
||||
AlignedByteOffset: _D3D11_APPEND_ALIGNED_ELEMENT,
|
||||
InputSlotClass: _D3D11_INPUT_PER_VERTEX_DATA,
|
||||
InstanceDataStepRate: 0,
|
||||
},
|
||||
{
|
||||
SemanticName: &([]byte("COLOR\000"))[0],
|
||||
SemanticIndex: 0,
|
||||
Format: _DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||
InputSlot: 0,
|
||||
AlignedByteOffset: _D3D11_APPEND_ALIGNED_ELEMENT,
|
||||
InputSlotClass: _D3D11_INPUT_PER_VERTEX_DATA,
|
||||
InstanceDataStepRate: 0,
|
||||
},
|
||||
}
|
||||
|
||||
func blendFactorToBlend11(f graphicsdriver.BlendFactor, alpha bool) _D3D11_BLEND {
|
||||
switch f {
|
||||
case graphicsdriver.BlendFactorZero:
|
||||
return _D3D11_BLEND_ZERO
|
||||
case graphicsdriver.BlendFactorOne:
|
||||
return _D3D11_BLEND_ONE
|
||||
case graphicsdriver.BlendFactorSourceColor:
|
||||
if alpha {
|
||||
return _D3D11_BLEND_SRC_ALPHA
|
||||
}
|
||||
return _D3D11_BLEND_SRC_COLOR
|
||||
case graphicsdriver.BlendFactorOneMinusSourceColor:
|
||||
if alpha {
|
||||
return _D3D11_BLEND_INV_SRC_ALPHA
|
||||
}
|
||||
return _D3D11_BLEND_INV_SRC_COLOR
|
||||
case graphicsdriver.BlendFactorSourceAlpha:
|
||||
return _D3D11_BLEND_SRC_ALPHA
|
||||
case graphicsdriver.BlendFactorOneMinusSourceAlpha:
|
||||
return _D3D11_BLEND_INV_SRC_ALPHA
|
||||
case graphicsdriver.BlendFactorDestinationColor:
|
||||
if alpha {
|
||||
return _D3D11_BLEND_DEST_ALPHA
|
||||
}
|
||||
return _D3D11_BLEND_DEST_COLOR
|
||||
case graphicsdriver.BlendFactorOneMinusDestinationColor:
|
||||
if alpha {
|
||||
return _D3D11_BLEND_INV_DEST_ALPHA
|
||||
}
|
||||
return _D3D11_BLEND_INV_DEST_COLOR
|
||||
case graphicsdriver.BlendFactorDestinationAlpha:
|
||||
return _D3D11_BLEND_DEST_ALPHA
|
||||
case graphicsdriver.BlendFactorOneMinusDestinationAlpha:
|
||||
return _D3D11_BLEND_INV_DEST_ALPHA
|
||||
case graphicsdriver.BlendFactorSourceAlphaSaturated:
|
||||
return _D3D11_BLEND_SRC_ALPHA_SAT
|
||||
default:
|
||||
panic(fmt.Sprintf("directx: invalid blend factor: %d", f))
|
||||
}
|
||||
}
|
||||
|
||||
func blendOperationToBlendOp11(o graphicsdriver.BlendOperation) _D3D11_BLEND_OP {
|
||||
switch o {
|
||||
case graphicsdriver.BlendOperationAdd:
|
||||
return _D3D11_BLEND_OP_ADD
|
||||
case graphicsdriver.BlendOperationSubtract:
|
||||
return _D3D11_BLEND_OP_SUBTRACT
|
||||
case graphicsdriver.BlendOperationReverseSubtract:
|
||||
return _D3D11_BLEND_OP_REV_SUBTRACT
|
||||
case graphicsdriver.BlendOperationMin:
|
||||
return _D3D11_BLEND_OP_MIN
|
||||
case graphicsdriver.BlendOperationMax:
|
||||
return _D3D11_BLEND_OP_MAX
|
||||
default:
|
||||
panic(fmt.Sprintf("directx: invalid blend operation: %d", o))
|
||||
}
|
||||
}
|
||||
|
||||
type blendStateKey struct {
|
||||
blend graphicsdriver.Blend
|
||||
writeMask uint8
|
||||
}
|
||||
|
||||
type graphics11 struct {
|
||||
graphicsInfra *graphicsInfra
|
||||
|
||||
featureLevel _D3D_FEATURE_LEVEL
|
||||
|
||||
device *_ID3D11Device
|
||||
deviceContext *_ID3D11DeviceContext
|
||||
|
||||
images map[graphicsdriver.ImageID]*image11
|
||||
screenImage *image11
|
||||
nextImageID graphicsdriver.ImageID
|
||||
|
||||
shaders map[graphicsdriver.ShaderID]*shader11
|
||||
nextShaderID graphicsdriver.ShaderID
|
||||
|
||||
vertexBuffer *_ID3D11Buffer
|
||||
vertexBufferSizeInBytes uint32
|
||||
|
||||
indexBuffer *_ID3D11Buffer
|
||||
indexBufferSizeInBytes uint32
|
||||
|
||||
rasterizerState *_ID3D11RasterizerState
|
||||
samplerState *_ID3D11SamplerState
|
||||
blendStates map[blendStateKey]*_ID3D11BlendState
|
||||
depthStencilStates map[stencilMode]*_ID3D11DepthStencilState
|
||||
|
||||
vsyncEnabled bool
|
||||
window windows.HWND
|
||||
|
||||
newScreenWidth int
|
||||
newScreenHeight int
|
||||
}
|
||||
|
||||
func newGraphics11(useWARP bool, useDebugLayer bool) (gr11 *graphics11, ferr error) {
|
||||
g := &graphics11{
|
||||
vsyncEnabled: true,
|
||||
}
|
||||
|
||||
driverType := _D3D_DRIVER_TYPE_HARDWARE
|
||||
if useWARP {
|
||||
driverType = _D3D_DRIVER_TYPE_WARP
|
||||
}
|
||||
|
||||
var flags _D3D11_CREATE_DEVICE_FLAG
|
||||
if useDebugLayer {
|
||||
flags |= _D3D11_CREATE_DEVICE_DEBUG
|
||||
}
|
||||
|
||||
// Avoid _D3D_FEATURE_LEVEL_11_1 as DirectX 11.0 doesn't recognize this.
|
||||
// Avoid _D3D_FEATURE_LEVEL_9_* for some shaders features (#1431).
|
||||
featureLevels := []_D3D_FEATURE_LEVEL{
|
||||
_D3D_FEATURE_LEVEL_11_0,
|
||||
_D3D_FEATURE_LEVEL_10_1,
|
||||
_D3D_FEATURE_LEVEL_10_0,
|
||||
}
|
||||
|
||||
// Apparently, adapter must be nil if the driver type is not unknown. This is not documented explicitly.
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-d3d11createdevice
|
||||
d, fl, ctx, err := _D3D11CreateDevice(nil, driverType, 0, uint32(flags), featureLevels, true, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
g.device = (*_ID3D11Device)(d)
|
||||
g.featureLevel = fl
|
||||
g.deviceContext = (*_ID3D11DeviceContext)(ctx)
|
||||
|
||||
// Get IDXGIFactory from the current device and use it, instead of CreateDXGIFactory.
|
||||
// Or, MakeWindowAssociation doesn't work well (#2661).
|
||||
dd, err := g.device.QueryInterface(&_IID_IDXGIDevice)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dxgiDevice := (*_IDXGIDevice)(dd)
|
||||
defer dxgiDevice.Release()
|
||||
|
||||
dxgiAdapter, err := dxgiDevice.GetAdapter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer dxgiAdapter.Release()
|
||||
|
||||
df, err := dxgiAdapter.GetParent(&_IID_IDXGIFactory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dxgiFactory := (*_IDXGIFactory)(df)
|
||||
|
||||
gi, err := newGraphicsInfra(dxgiFactory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
g.graphicsInfra = gi
|
||||
defer func() {
|
||||
if ferr != nil {
|
||||
g.graphicsInfra.release()
|
||||
g.graphicsInfra = nil
|
||||
}
|
||||
}()
|
||||
|
||||
g.deviceContext.IASetPrimitiveTopology(_D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST)
|
||||
|
||||
// Set the rasterizer state.
|
||||
if g.rasterizerState == nil {
|
||||
rs, err := g.device.CreateRasterizerState(&_D3D11_RASTERIZER_DESC{
|
||||
FillMode: _D3D11_FILL_SOLID,
|
||||
CullMode: _D3D11_CULL_NONE,
|
||||
FrontCounterClockwise: 0,
|
||||
DepthBias: 0,
|
||||
DepthBiasClamp: 0,
|
||||
SlopeScaledDepthBias: 0,
|
||||
DepthClipEnable: 0,
|
||||
ScissorEnable: 1,
|
||||
MultisampleEnable: 0,
|
||||
AntialiasedLineEnable: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
g.rasterizerState = rs
|
||||
}
|
||||
g.deviceContext.RSSetState(g.rasterizerState)
|
||||
|
||||
// Set the sampler state.
|
||||
if g.samplerState == nil {
|
||||
s, err := g.device.CreateSamplerState(&_D3D11_SAMPLER_DESC{
|
||||
Filter: _D3D11_FILTER_MIN_MAG_MIP_POINT,
|
||||
AddressU: _D3D11_TEXTURE_ADDRESS_WRAP,
|
||||
AddressV: _D3D11_TEXTURE_ADDRESS_WRAP,
|
||||
AddressW: _D3D11_TEXTURE_ADDRESS_WRAP,
|
||||
ComparisonFunc: _D3D11_COMPARISON_NEVER,
|
||||
MinLOD: -math.MaxFloat32,
|
||||
MaxLOD: math.MaxFloat32,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
g.samplerState = s
|
||||
}
|
||||
g.deviceContext.PSSetSamplers(0, []*_ID3D11SamplerState{g.samplerState})
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func (g *graphics11) Initialize() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *graphics11) Begin() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *graphics11) End(present bool) error {
|
||||
if !present {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := g.graphicsInfra.present(g.vsyncEnabled); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if g.newScreenWidth != 0 && g.newScreenHeight != 0 {
|
||||
if g.screenImage != nil {
|
||||
// ResizeBuffer requires all the related resources released,
|
||||
// so release the swapchain's buffer.
|
||||
// Do not dispose the screen image itself since the image's ID is still used.
|
||||
g.screenImage.disposeBuffers()
|
||||
}
|
||||
|
||||
if err := g.graphicsInfra.resizeSwapChain(g.newScreenWidth, g.newScreenHeight); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t, err := g.graphicsInfra.getBuffer(0, &_IID_ID3D11Texture2D)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.screenImage.width = g.newScreenWidth
|
||||
g.screenImage.height = g.newScreenHeight
|
||||
g.screenImage.texture = (*_ID3D11Texture2D)(t)
|
||||
|
||||
g.newScreenWidth = 0
|
||||
g.newScreenHeight = 0
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *graphics11) SetWindow(window uintptr) {
|
||||
g.window = windows.HWND(window)
|
||||
// TODO: need to update the swap chain?
|
||||
}
|
||||
|
||||
func (g *graphics11) SetTransparent(transparent bool) {
|
||||
// TODO: Implement this?
|
||||
}
|
||||
|
||||
func (g *graphics11) SetVertices(vertices []float32, indices []uint32) error {
|
||||
if size := pow2(uint32(len(vertices)) * uint32(unsafe.Sizeof(vertices[0]))); g.vertexBufferSizeInBytes < size {
|
||||
if g.vertexBuffer != nil {
|
||||
g.vertexBuffer.Release()
|
||||
g.vertexBuffer = nil
|
||||
}
|
||||
b, err := g.device.CreateBuffer(&_D3D11_BUFFER_DESC{
|
||||
ByteWidth: size,
|
||||
Usage: _D3D11_USAGE_DYNAMIC,
|
||||
BindFlags: uint32(_D3D11_BIND_VERTEX_BUFFER),
|
||||
CPUAccessFlags: uint32(_D3D11_CPU_ACCESS_WRITE),
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.vertexBuffer = b
|
||||
g.vertexBufferSizeInBytes = size
|
||||
g.deviceContext.IASetVertexBuffers(0, []*_ID3D11Buffer{g.vertexBuffer},
|
||||
[]uint32{graphics.VertexFloatCount * uint32(unsafe.Sizeof(vertices[0]))}, []uint32{0})
|
||||
}
|
||||
if size := pow2(uint32(len(indices)) * uint32(unsafe.Sizeof(indices[0]))); g.indexBufferSizeInBytes < size {
|
||||
if g.indexBuffer != nil {
|
||||
g.indexBuffer.Release()
|
||||
g.indexBuffer = nil
|
||||
}
|
||||
b, err := g.device.CreateBuffer(&_D3D11_BUFFER_DESC{
|
||||
ByteWidth: size,
|
||||
Usage: _D3D11_USAGE_DYNAMIC,
|
||||
BindFlags: uint32(_D3D11_BIND_INDEX_BUFFER),
|
||||
CPUAccessFlags: uint32(_D3D11_CPU_ACCESS_WRITE),
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.indexBuffer = b
|
||||
g.indexBufferSizeInBytes = size
|
||||
g.deviceContext.IASetIndexBuffer(g.indexBuffer, _DXGI_FORMAT_R32_UINT, 0)
|
||||
}
|
||||
|
||||
// Copy the vertices data.
|
||||
{
|
||||
var mapped _D3D11_MAPPED_SUBRESOURCE
|
||||
if err := g.deviceContext.Map(unsafe.Pointer(g.vertexBuffer), 0, _D3D11_MAP_WRITE_DISCARD, 0, &mapped); err != nil {
|
||||
return err
|
||||
}
|
||||
copy(unsafe.Slice((*float32)(mapped.pData), len(vertices)), vertices)
|
||||
g.deviceContext.Unmap(unsafe.Pointer(g.vertexBuffer), 0)
|
||||
}
|
||||
|
||||
// Copy the indices data.
|
||||
{
|
||||
var mapped _D3D11_MAPPED_SUBRESOURCE
|
||||
if err := g.deviceContext.Map(unsafe.Pointer(g.indexBuffer), 0, _D3D11_MAP_WRITE_DISCARD, 0, &mapped); err != nil {
|
||||
return err
|
||||
}
|
||||
copy(unsafe.Slice((*uint32)(mapped.pData), len(indices)), indices)
|
||||
g.deviceContext.Unmap(unsafe.Pointer(g.indexBuffer), 0)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *graphics11) NewImage(width, height int) (graphicsdriver.Image, error) {
|
||||
t, err := g.device.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{
|
||||
Width: uint32(graphics.InternalImageSize(width)),
|
||||
Height: uint32(graphics.InternalImageSize(height)),
|
||||
MipLevels: 1, // 0 doesn't work when shrinking the image.
|
||||
ArraySize: 1,
|
||||
Format: _DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
SampleDesc: _DXGI_SAMPLE_DESC{
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
Usage: _D3D11_USAGE_DEFAULT,
|
||||
BindFlags: uint32(_D3D11_BIND_SHADER_RESOURCE | _D3D11_BIND_RENDER_TARGET),
|
||||
CPUAccessFlags: 0,
|
||||
MiscFlags: 0,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
i := &image11{
|
||||
graphics: g,
|
||||
id: g.genNextImageID(),
|
||||
width: width,
|
||||
height: height,
|
||||
texture: t,
|
||||
}
|
||||
g.addImage(i)
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (g *graphics11) NewScreenFramebufferImage(width, height int) (graphicsdriver.Image, error) {
|
||||
imageWidth := width
|
||||
imageHeight := height
|
||||
if g.screenImage != nil {
|
||||
imageWidth = g.screenImage.width
|
||||
imageHeight = g.screenImage.height
|
||||
g.screenImage.Dispose()
|
||||
g.screenImage = nil
|
||||
}
|
||||
|
||||
if g.graphicsInfra.isSwapChainInited() {
|
||||
g.newScreenWidth, g.newScreenHeight = width, height
|
||||
} else {
|
||||
if err := g.graphicsInfra.initSwapChain(width, height, unsafe.Pointer(g.device), g.window); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
t, err := g.graphicsInfra.getBuffer(0, &_IID_ID3D11Texture2D)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
i := &image11{
|
||||
graphics: g,
|
||||
id: g.genNextImageID(),
|
||||
width: imageWidth,
|
||||
height: imageHeight,
|
||||
screen: true,
|
||||
texture: (*_ID3D11Texture2D)(t),
|
||||
}
|
||||
g.addImage(i)
|
||||
g.screenImage = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (g *graphics11) addImage(img *image11) {
|
||||
if g.images == nil {
|
||||
g.images = map[graphicsdriver.ImageID]*image11{}
|
||||
}
|
||||
if _, ok := g.images[img.id]; ok {
|
||||
panic(fmt.Sprintf("directx: image ID %d was already registered", img.id))
|
||||
}
|
||||
g.images[img.id] = img
|
||||
}
|
||||
|
||||
func (g *graphics11) removeImage(image *image11) {
|
||||
delete(g.images, image.id)
|
||||
}
|
||||
|
||||
func (g *graphics11) SetVsyncEnabled(enabled bool) {
|
||||
g.vsyncEnabled = enabled
|
||||
}
|
||||
|
||||
func (g *graphics11) NeedsClearingScreen() bool {
|
||||
// TODO: Confirm this is really true.
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *graphics11) MaxImageSize() int {
|
||||
switch g.featureLevel {
|
||||
case _D3D_FEATURE_LEVEL_10_0:
|
||||
return 8192
|
||||
case _D3D_FEATURE_LEVEL_10_1:
|
||||
return 8192
|
||||
case _D3D_FEATURE_LEVEL_11_0:
|
||||
return 16384
|
||||
default:
|
||||
panic(fmt.Sprintf("directx: invalid feature level: 0x%x", g.featureLevel))
|
||||
}
|
||||
}
|
||||
|
||||
func (g *graphics11) NewShader(program *shaderir.Program) (graphicsdriver.Shader, error) {
|
||||
vs, ps, offsets := hlsl.Compile(program)
|
||||
vsh, psh, err := compileShader(vs, ps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s := &shader11{
|
||||
graphics: g,
|
||||
id: g.genNextShaderID(),
|
||||
uniformTypes: program.Uniforms,
|
||||
uniformOffsets: offsets,
|
||||
vertexShaderBlob: vsh,
|
||||
pixelShaderBlob: psh,
|
||||
}
|
||||
g.addShader(s)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (g *graphics11) addShader(s *shader11) {
|
||||
if g.shaders == nil {
|
||||
g.shaders = map[graphicsdriver.ShaderID]*shader11{}
|
||||
}
|
||||
if _, ok := g.shaders[s.id]; ok {
|
||||
panic(fmt.Sprintf("directx: shader ID %d was already registered", s.id))
|
||||
}
|
||||
g.shaders[s.id] = s
|
||||
}
|
||||
|
||||
func (g *graphics11) removeShader(s *shader11) {
|
||||
s.disposeImpl()
|
||||
delete(g.shaders, s.id)
|
||||
}
|
||||
|
||||
func (g *graphics11) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.ShaderImageCount]graphicsdriver.ImageID, shaderID graphicsdriver.ShaderID, dstRegions []graphicsdriver.DstRegion, indexOffset int, blend graphicsdriver.Blend, uniforms []uint32, fillRule graphicsdriver.FillRule) error {
|
||||
// Remove bound textures first. This is needed to avoid warnings on the debugger.
|
||||
g.deviceContext.OMSetRenderTargets([]*_ID3D11RenderTargetView{nil}, nil)
|
||||
srvs := [graphics.ShaderImageCount]*_ID3D11ShaderResourceView{}
|
||||
g.deviceContext.PSSetShaderResources(0, srvs[:])
|
||||
|
||||
dst := g.images[dstID]
|
||||
var srcs [graphics.ShaderImageCount]*image11
|
||||
for i, id := range srcIDs {
|
||||
img := g.images[id]
|
||||
if img == nil {
|
||||
continue
|
||||
}
|
||||
srcs[i] = img
|
||||
}
|
||||
|
||||
w, h := dst.internalSize()
|
||||
g.deviceContext.RSSetViewports([]_D3D11_VIEWPORT{
|
||||
{
|
||||
TopLeftX: 0,
|
||||
TopLeftY: 0,
|
||||
Width: float32(w),
|
||||
Height: float32(h),
|
||||
MinDepth: 0,
|
||||
MaxDepth: 1,
|
||||
},
|
||||
})
|
||||
|
||||
if err := dst.setAsRenderTarget(fillRule != graphicsdriver.FillAll); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set the shader parameters.
|
||||
shader := g.shaders[shaderID]
|
||||
if err := shader.use(uniforms, srcs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if fillRule == graphicsdriver.FillAll {
|
||||
bs, err := g.blendState(blend, noStencil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.deviceContext.OMSetBlendState(bs, nil, 0xffffffff)
|
||||
|
||||
dss, err := g.depthStencilState(noStencil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.deviceContext.OMSetDepthStencilState(dss, 0)
|
||||
}
|
||||
|
||||
for _, dstRegion := range dstRegions {
|
||||
g.deviceContext.RSSetScissorRects([]_D3D11_RECT{
|
||||
{
|
||||
left: int32(dstRegion.Region.Min.X),
|
||||
top: int32(dstRegion.Region.Min.Y),
|
||||
right: int32(dstRegion.Region.Max.X),
|
||||
bottom: int32(dstRegion.Region.Max.Y),
|
||||
},
|
||||
})
|
||||
|
||||
switch fillRule {
|
||||
case graphicsdriver.FillAll:
|
||||
g.deviceContext.DrawIndexed(uint32(dstRegion.IndexCount), uint32(indexOffset), 0)
|
||||
case graphicsdriver.NonZero:
|
||||
bs, err := g.blendState(blend, incrementStencil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.deviceContext.OMSetBlendState(bs, nil, 0xffffffff)
|
||||
dss, err := g.depthStencilState(incrementStencil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.deviceContext.OMSetDepthStencilState(dss, 0)
|
||||
g.deviceContext.DrawIndexed(uint32(dstRegion.IndexCount), uint32(indexOffset), 0)
|
||||
case graphicsdriver.EvenOdd:
|
||||
bs, err := g.blendState(blend, invertStencil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.deviceContext.OMSetBlendState(bs, nil, 0xffffffff)
|
||||
dss, err := g.depthStencilState(invertStencil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.deviceContext.OMSetDepthStencilState(dss, 0)
|
||||
g.deviceContext.DrawIndexed(uint32(dstRegion.IndexCount), uint32(indexOffset), 0)
|
||||
}
|
||||
|
||||
if fillRule != graphicsdriver.FillAll {
|
||||
bs, err := g.blendState(blend, drawWithStencil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.deviceContext.OMSetBlendState(bs, nil, 0xffffffff)
|
||||
dss, err := g.depthStencilState(drawWithStencil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.deviceContext.OMSetDepthStencilState(dss, 0)
|
||||
g.deviceContext.DrawIndexed(uint32(dstRegion.IndexCount), uint32(indexOffset), 0)
|
||||
}
|
||||
|
||||
indexOffset += dstRegion.IndexCount
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *graphics11) genNextImageID() graphicsdriver.ImageID {
|
||||
g.nextImageID++
|
||||
return g.nextImageID
|
||||
}
|
||||
|
||||
func (g *graphics11) genNextShaderID() graphicsdriver.ShaderID {
|
||||
g.nextShaderID++
|
||||
return g.nextShaderID
|
||||
}
|
||||
|
||||
func (g *graphics11) blendState(blend graphicsdriver.Blend, stencilMode stencilMode) (*_ID3D11BlendState, error) {
|
||||
var writeMask uint8
|
||||
if stencilMode == noStencil || stencilMode == drawWithStencil {
|
||||
writeMask = uint8(_D3D11_COLOR_WRITE_ENABLE_ALL)
|
||||
}
|
||||
|
||||
key := blendStateKey{
|
||||
blend: blend,
|
||||
writeMask: writeMask,
|
||||
}
|
||||
if bs, ok := g.blendStates[key]; ok {
|
||||
return bs, nil
|
||||
}
|
||||
|
||||
bs, err := g.device.CreateBlendState(&_D3D11_BLEND_DESC{
|
||||
AlphaToCoverageEnable: 0,
|
||||
IndependentBlendEnable: 0,
|
||||
RenderTarget: [8]_D3D11_RENDER_TARGET_BLEND_DESC{
|
||||
{
|
||||
BlendEnable: 1,
|
||||
SrcBlend: blendFactorToBlend11(blend.BlendFactorSourceRGB, false),
|
||||
DestBlend: blendFactorToBlend11(blend.BlendFactorDestinationRGB, false),
|
||||
BlendOp: blendOperationToBlendOp11(blend.BlendOperationRGB),
|
||||
SrcBlendAlpha: blendFactorToBlend11(blend.BlendFactorSourceAlpha, true),
|
||||
DestBlendAlpha: blendFactorToBlend11(blend.BlendFactorDestinationAlpha, true),
|
||||
BlendOpAlpha: blendOperationToBlendOp11(blend.BlendOperationAlpha),
|
||||
RenderTargetWriteMask: writeMask,
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if g.blendStates == nil {
|
||||
g.blendStates = map[blendStateKey]*_ID3D11BlendState{}
|
||||
}
|
||||
g.blendStates[key] = bs
|
||||
return bs, nil
|
||||
}
|
||||
|
||||
func (g *graphics11) depthStencilState(mode stencilMode) (*_ID3D11DepthStencilState, error) {
|
||||
if s, ok := g.depthStencilStates[mode]; ok {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
desc := &_D3D11_DEPTH_STENCIL_DESC{
|
||||
DepthEnable: 0,
|
||||
DepthWriteMask: _D3D11_DEPTH_WRITE_MASK_ALL,
|
||||
DepthFunc: _D3D11_COMPARISON_LESS,
|
||||
StencilEnable: 0,
|
||||
StencilReadMask: _D3D11_DEFAULT_STENCIL_READ_MASK,
|
||||
StencilWriteMask: _D3D11_DEFAULT_STENCIL_WRITE_MASK,
|
||||
FrontFace: _D3D11_DEPTH_STENCILOP_DESC{
|
||||
StencilFailOp: _D3D11_STENCIL_OP_KEEP,
|
||||
StencilDepthFailOp: _D3D11_STENCIL_OP_KEEP,
|
||||
StencilPassOp: _D3D11_STENCIL_OP_KEEP,
|
||||
StencilFunc: _D3D11_COMPARISON_ALWAYS,
|
||||
},
|
||||
BackFace: _D3D11_DEPTH_STENCILOP_DESC{
|
||||
StencilFailOp: _D3D11_STENCIL_OP_KEEP,
|
||||
StencilDepthFailOp: _D3D11_STENCIL_OP_KEEP,
|
||||
StencilPassOp: _D3D11_STENCIL_OP_KEEP,
|
||||
StencilFunc: _D3D11_COMPARISON_ALWAYS,
|
||||
},
|
||||
}
|
||||
switch mode {
|
||||
case incrementStencil:
|
||||
desc.StencilEnable = 1
|
||||
desc.FrontFace.StencilPassOp = _D3D11_STENCIL_OP_INCR
|
||||
desc.BackFace.StencilPassOp = _D3D11_STENCIL_OP_DECR
|
||||
case invertStencil:
|
||||
desc.StencilEnable = 1
|
||||
desc.FrontFace.StencilPassOp = _D3D11_STENCIL_OP_INVERT
|
||||
desc.BackFace.StencilPassOp = _D3D11_STENCIL_OP_INVERT
|
||||
case drawWithStencil:
|
||||
desc.StencilEnable = 1
|
||||
desc.FrontFace.StencilFunc = _D3D11_COMPARISON_NOT_EQUAL
|
||||
desc.BackFace.StencilFunc = _D3D11_COMPARISON_NOT_EQUAL
|
||||
}
|
||||
|
||||
s, err := g.device.CreateDepthStencilState(desc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if g.depthStencilStates == nil {
|
||||
g.depthStencilStates = map[stencilMode]*_ID3D11DepthStencilState{}
|
||||
}
|
||||
g.depthStencilStates[mode] = s
|
||||
return s, nil
|
||||
}
|
||||
Generated
Vendored
+1176
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+374
@@ -0,0 +1,374 @@
|
||||
// Copyright 2022 The Ebiten Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package directx
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/microsoftgdk"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/winver"
|
||||
)
|
||||
|
||||
type stencilMode int
|
||||
|
||||
const (
|
||||
noStencil stencilMode = iota
|
||||
incrementStencil
|
||||
invertStencil
|
||||
drawWithStencil
|
||||
)
|
||||
|
||||
const frameCount = 2
|
||||
|
||||
func pow2(x uint32) uint32 {
|
||||
if x > (math.MaxUint32+1)/2 {
|
||||
return math.MaxUint32
|
||||
}
|
||||
|
||||
var p2 uint32 = 1
|
||||
for p2 < x {
|
||||
p2 *= 2
|
||||
}
|
||||
return p2
|
||||
}
|
||||
|
||||
func parseFeatureLevel(str string) (_D3D_FEATURE_LEVEL, bool) {
|
||||
switch str {
|
||||
case "11_0":
|
||||
return _D3D_FEATURE_LEVEL_11_0, true
|
||||
case "11_1":
|
||||
return _D3D_FEATURE_LEVEL_11_1, true
|
||||
case "12_0":
|
||||
return _D3D_FEATURE_LEVEL_12_0, true
|
||||
case "12_1":
|
||||
return _D3D_FEATURE_LEVEL_12_1, true
|
||||
case "12_2":
|
||||
return _D3D_FEATURE_LEVEL_12_2, true
|
||||
default:
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
|
||||
// NewGraphics creates an implementation of graphicsdriver.Graphics for DirectX.
|
||||
// The returned graphics value is nil iff the error is not nil.
|
||||
func NewGraphics() (graphicsdriver.Graphics, error) {
|
||||
if !isD3DCompilerDLLAvailable() {
|
||||
return nil, fmt.Errorf("directx: d3dcompiler_*.dll is missing in this environment")
|
||||
}
|
||||
|
||||
var useWARP bool
|
||||
var useDebugLayer bool
|
||||
version := 11
|
||||
|
||||
// Specify the feature level 11 by default.
|
||||
// Some old cards don't work well with the default feature level (#2447, #2486).
|
||||
featureLevel := _D3D_FEATURE_LEVEL_11_0
|
||||
|
||||
// Parse a special environment variable for backward compatibility.
|
||||
if env := os.Getenv("EBITENGINE_DIRECTX_FEATURE_LEVEL"); env != "" {
|
||||
if fl, ok := parseFeatureLevel(env); ok {
|
||||
featureLevel = fl
|
||||
}
|
||||
}
|
||||
|
||||
env := os.Getenv("EBITENGINE_DIRECTX")
|
||||
if env == "" {
|
||||
// For backward compatibility, read the EBITEN_ version.
|
||||
env = os.Getenv("EBITEN_DIRECTX")
|
||||
}
|
||||
|
||||
for _, t := range strings.Split(env, ",") {
|
||||
t := strings.TrimSpace(t)
|
||||
switch {
|
||||
case t == "warp":
|
||||
// TODO: Is WARP available on Xbox?
|
||||
useWARP = true
|
||||
case t == "debug":
|
||||
useDebugLayer = true
|
||||
case strings.HasPrefix(t, "version="):
|
||||
v, err := strconv.Atoi(t[len("version="):])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
version = v
|
||||
case strings.HasPrefix(t, "featurelevel="):
|
||||
fl, ok := parseFeatureLevel(t[len("featurelevel="):])
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
featureLevel = fl
|
||||
}
|
||||
}
|
||||
|
||||
// On Xbox, only DirectX 12 is available.
|
||||
if microsoftgdk.IsXbox() {
|
||||
version = 12
|
||||
}
|
||||
|
||||
switch version {
|
||||
case 11:
|
||||
g, err := newGraphics11(useWARP, useDebugLayer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return g, nil
|
||||
case 12:
|
||||
g, err := newGraphics12(useWARP, useDebugLayer, featureLevel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return g, nil
|
||||
default:
|
||||
panic(fmt.Sprintf("directx: unexpected DirectX version: %d", version))
|
||||
}
|
||||
}
|
||||
|
||||
type graphicsInfra struct {
|
||||
factory *_IDXGIFactory
|
||||
swapChain *_IDXGISwapChain
|
||||
swapChain4 *_IDXGISwapChain4
|
||||
|
||||
allowTearing bool
|
||||
|
||||
// occluded reports whether the screen is invisible or not.
|
||||
occluded bool
|
||||
|
||||
// lastTime is the last time for rendering.
|
||||
lastTime time.Time
|
||||
|
||||
bufferCount int
|
||||
}
|
||||
|
||||
// newGraphicsInfra takes the ownership of the given factory.
|
||||
func newGraphicsInfra(factory *_IDXGIFactory) (*graphicsInfra, error) {
|
||||
g := &graphicsInfra{
|
||||
factory: factory,
|
||||
}
|
||||
runtime.SetFinalizer(g, (*graphicsInfra).release)
|
||||
|
||||
if f, err := g.factory.QueryInterface(&_IID_IDXGIFactory5); err == nil && f != nil {
|
||||
factory := (*_IDXGIFactory5)(f)
|
||||
defer factory.Release()
|
||||
|
||||
var allowTearing int32
|
||||
if err := factory.CheckFeatureSupport(_DXGI_FEATURE_PRESENT_ALLOW_TEARING, unsafe.Pointer(&allowTearing), uint32(unsafe.Sizeof(allowTearing))); err == nil && allowTearing != 0 {
|
||||
g.allowTearing = true
|
||||
}
|
||||
}
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func (g *graphicsInfra) release() {
|
||||
if g.factory != nil {
|
||||
g.factory.Release()
|
||||
g.factory = nil
|
||||
}
|
||||
if g.swapChain != nil {
|
||||
g.swapChain.Release()
|
||||
g.swapChain = nil
|
||||
}
|
||||
if g.swapChain4 != nil {
|
||||
g.swapChain4.Release()
|
||||
g.swapChain4 = nil
|
||||
}
|
||||
}
|
||||
|
||||
// appendAdapters appends found adapters to the given adapters.
|
||||
// Releasing them is the caller's responsibility.
|
||||
//
|
||||
// warpForDX12 is valid only for DirectX 12.
|
||||
func (g *graphicsInfra) appendAdapters(adapters []*_IDXGIAdapter1, warpForDX12 bool) ([]*_IDXGIAdapter1, error) {
|
||||
f, err := g.factory.QueryInterface(&_IID_IDXGIFactory4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f == nil {
|
||||
return nil, fmt.Errorf("directx: IID_IDXGIFactory4 was not available")
|
||||
}
|
||||
factory4 := (*_IDXGIFactory4)(f)
|
||||
defer factory4.Release()
|
||||
|
||||
if warpForDX12 {
|
||||
a, err := factory4.EnumWarpAdapter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
adapters = append(adapters, a)
|
||||
return adapters, nil
|
||||
}
|
||||
|
||||
for i := uint32(0); ; i++ {
|
||||
a, err := factory4.EnumAdapters1(i)
|
||||
if errors.Is(err, _DXGI_ERROR_NOT_FOUND) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
adapters = append(adapters, a)
|
||||
}
|
||||
|
||||
return adapters, nil
|
||||
}
|
||||
|
||||
func (g *graphicsInfra) isSwapChainInited() bool {
|
||||
return g.swapChain != nil
|
||||
}
|
||||
|
||||
func (g *graphicsInfra) initSwapChain(width, height int, device unsafe.Pointer, window windows.HWND) (ferr error) {
|
||||
if g.swapChain != nil {
|
||||
return fmt.Errorf("directx: swap chain must not be initialized at initSwapChain, but is already done")
|
||||
}
|
||||
|
||||
// Create a swap chain.
|
||||
//
|
||||
// DXGI_ALPHA_MODE_PREMULTIPLIED doesn't work with a HWND well.
|
||||
//
|
||||
// IDXGIFactory::CreateSwapChain: Alpha blended swapchains must be created with CreateSwapChainForComposition,
|
||||
// or CreateSwapChainForCoreWindow with the DXGI_SWAP_CHAIN_FLAG_FOREGROUND_LAYER flag
|
||||
//
|
||||
// Use *_SEQUENTIAL swap effects to follow the Mozilla way:
|
||||
// https://github.com/mozilla/gecko-dev/blob/0907529ff72c456ddb47839f5f7ba16291f28dce/gfx/layers/d3d11/CompositorD3D11.cpp#L167-L254
|
||||
desc := &_DXGI_SWAP_CHAIN_DESC{
|
||||
BufferDesc: _DXGI_MODE_DESC{
|
||||
Width: uint32(width),
|
||||
Height: uint32(height),
|
||||
Format: _DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
},
|
||||
SampleDesc: _DXGI_SAMPLE_DESC{
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
BufferUsage: _DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
||||
BufferCount: frameCount,
|
||||
OutputWindow: window,
|
||||
Windowed: 1,
|
||||
SwapEffect: _DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
|
||||
}
|
||||
|
||||
// DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL/DISCARD are not supported for older Windows than 10 or DirectX 12.
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/dxgi/ne-dxgi-dxgi_swap_effect
|
||||
if !winver.IsWindows10OrGreater() {
|
||||
desc.SwapEffect = _DXGI_SWAP_EFFECT_SEQUENTIAL
|
||||
// With the non-flip (bitblt) mode, the buffer count should be 1. See also:
|
||||
// * https://bugzilla.mozilla.org/show_bug.cgi?id=1419293#c18
|
||||
// * https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/dxgi-flip-model
|
||||
desc.BufferCount = 1
|
||||
}
|
||||
|
||||
g.bufferCount = int(desc.BufferCount)
|
||||
|
||||
if g.allowTearing {
|
||||
desc.Flags |= uint32(_DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING)
|
||||
}
|
||||
s, err := g.factory.CreateSwapChain(device, desc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.swapChain = s
|
||||
defer func() {
|
||||
if ferr != nil {
|
||||
g.release()
|
||||
}
|
||||
}()
|
||||
|
||||
if s4, err := g.swapChain.QueryInterface(&_IID_IDXGISwapChain4); err == nil && s4 != nil {
|
||||
g.swapChain4 = (*_IDXGISwapChain4)(s4)
|
||||
}
|
||||
|
||||
// MakeWindowAssociation should be called after swap chain creation.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgifactory-makewindowassociation
|
||||
if err := g.factory.MakeWindowAssociation(window, _DXGI_MWA_NO_WINDOW_CHANGES|_DXGI_MWA_NO_ALT_ENTER); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *graphicsInfra) resizeSwapChain(width, height int) error {
|
||||
if g.swapChain == nil {
|
||||
return fmt.Errorf("directx: swap chain must be initialized at resizeSwapChain, but is not")
|
||||
}
|
||||
|
||||
var flag uint32
|
||||
if g.allowTearing {
|
||||
flag |= uint32(_DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING)
|
||||
}
|
||||
if err := g.swapChain.ResizeBuffers(uint32(g.bufferCount), uint32(width), uint32(height), _DXGI_FORMAT_B8G8R8A8_UNORM, flag); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *graphicsInfra) currentBackBufferIndex() (int, error) {
|
||||
if g.swapChain4 == nil {
|
||||
return 0, fmt.Errorf("directx: IDXGISwapChain4 is not available")
|
||||
}
|
||||
return int(g.swapChain4.GetCurrentBackBufferIndex()), nil
|
||||
}
|
||||
|
||||
func (g *graphicsInfra) present(vsyncEnabled bool) error {
|
||||
if g.swapChain == nil {
|
||||
return fmt.Errorf("directx: swap chain must be initialized at present, but is not")
|
||||
}
|
||||
|
||||
var syncInterval uint32
|
||||
var flags _DXGI_PRESENT
|
||||
if g.occluded {
|
||||
// The screen is not visible. Test whether we can resume.
|
||||
flags |= _DXGI_PRESENT_TEST
|
||||
} else {
|
||||
// Do actual rendering only when the screen is visible.
|
||||
if vsyncEnabled {
|
||||
syncInterval = 1
|
||||
} else if g.allowTearing {
|
||||
flags |= _DXGI_PRESENT_ALLOW_TEARING
|
||||
}
|
||||
}
|
||||
|
||||
occluded, err := g.swapChain.Present(syncInterval, uint32(flags))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.occluded = occluded
|
||||
|
||||
// Reduce FPS when the screen is invisible.
|
||||
now := time.Now()
|
||||
if g.occluded {
|
||||
if delta := 100*time.Millisecond - now.Sub(g.lastTime); delta > 0 {
|
||||
time.Sleep(delta)
|
||||
}
|
||||
}
|
||||
g.lastTime = now
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *graphicsInfra) getBuffer(buffer uint32, riid *windows.GUID) (unsafe.Pointer, error) {
|
||||
return g.swapChain.GetBuffer(buffer, riid)
|
||||
}
|
||||
Generated
Vendored
+216
@@ -0,0 +1,216 @@
|
||||
// Copyright 2023 The Ebitengine Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package directx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"unsafe"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
)
|
||||
|
||||
type image11 struct {
|
||||
graphics *graphics11
|
||||
id graphicsdriver.ImageID
|
||||
width int
|
||||
height int
|
||||
screen bool
|
||||
|
||||
texture *_ID3D11Texture2D
|
||||
stencil *_ID3D11Texture2D
|
||||
renderTargetView *_ID3D11RenderTargetView
|
||||
stencilView *_ID3D11DepthStencilView
|
||||
shaderResourceView *_ID3D11ShaderResourceView
|
||||
}
|
||||
|
||||
func (i *image11) internalSize() (int, int) {
|
||||
if i.screen {
|
||||
return i.width, i.height
|
||||
}
|
||||
return graphics.InternalImageSize(i.width), graphics.InternalImageSize(i.height)
|
||||
}
|
||||
|
||||
func (i *image11) ID() graphicsdriver.ImageID {
|
||||
return i.id
|
||||
}
|
||||
|
||||
func (i *image11) Dispose() {
|
||||
i.disposeBuffers()
|
||||
i.graphics.removeImage(i)
|
||||
}
|
||||
|
||||
func (i *image11) disposeBuffers() {
|
||||
if i.texture != nil {
|
||||
i.texture.Release()
|
||||
i.texture = nil
|
||||
}
|
||||
if i.stencil != nil {
|
||||
i.stencil.Release()
|
||||
i.stencil = nil
|
||||
}
|
||||
if i.renderTargetView != nil {
|
||||
i.renderTargetView.Release()
|
||||
i.renderTargetView = nil
|
||||
}
|
||||
if i.stencilView != nil {
|
||||
i.stencilView.Release()
|
||||
i.stencilView = nil
|
||||
}
|
||||
if i.shaderResourceView != nil {
|
||||
i.shaderResourceView.Release()
|
||||
i.shaderResourceView = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (i *image11) ReadPixels(args []graphicsdriver.PixelsArgs) error {
|
||||
var unionRegion image.Rectangle
|
||||
for _, a := range args {
|
||||
unionRegion = unionRegion.Union(a.Region)
|
||||
}
|
||||
|
||||
staging, err := i.graphics.device.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{
|
||||
Width: uint32(unionRegion.Dx()),
|
||||
Height: uint32(unionRegion.Dy()),
|
||||
MipLevels: 0,
|
||||
ArraySize: 1,
|
||||
Format: _DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
SampleDesc: _DXGI_SAMPLE_DESC{
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
Usage: _D3D11_USAGE_STAGING,
|
||||
BindFlags: 0,
|
||||
CPUAccessFlags: uint32(_D3D11_CPU_ACCESS_READ),
|
||||
MiscFlags: 0,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer staging.Release()
|
||||
|
||||
i.graphics.deviceContext.CopySubresourceRegion(unsafe.Pointer(staging), 0, 0, 0, 0, unsafe.Pointer(i.texture), 0, &_D3D11_BOX{
|
||||
left: uint32(unionRegion.Min.X),
|
||||
top: uint32(unionRegion.Min.Y),
|
||||
front: 0,
|
||||
right: uint32(unionRegion.Max.X),
|
||||
bottom: uint32(unionRegion.Max.Y),
|
||||
back: 1,
|
||||
})
|
||||
|
||||
var mapped _D3D11_MAPPED_SUBRESOURCE
|
||||
if err := i.graphics.deviceContext.Map(unsafe.Pointer(staging), 0, _D3D11_MAP_READ, 0, &mapped); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stride := int(mapped.RowPitch)
|
||||
srcPix := unsafe.Slice((*byte)(mapped.pData), stride*unionRegion.Dy())
|
||||
for _, a := range args {
|
||||
w := a.Region.Dx()
|
||||
if unionRegion == a.Region && stride == 4*w {
|
||||
copy(a.Pixels, srcPix)
|
||||
continue
|
||||
}
|
||||
offset := 4*(a.Region.Min.X-unionRegion.Min.X) + stride*(a.Region.Min.Y-unionRegion.Min.Y)
|
||||
for j := 0; j < a.Region.Dy(); j++ {
|
||||
copy(a.Pixels[j*4*w:(j+1)*4*w], srcPix[offset+j*stride:])
|
||||
}
|
||||
}
|
||||
|
||||
i.graphics.deviceContext.Unmap(unsafe.Pointer(staging), 0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *image11) WritePixels(args []graphicsdriver.PixelsArgs) error {
|
||||
for _, a := range args {
|
||||
i.graphics.deviceContext.UpdateSubresource(unsafe.Pointer(i.texture), 0, &_D3D11_BOX{
|
||||
left: uint32(a.Region.Min.X),
|
||||
top: uint32(a.Region.Min.Y),
|
||||
front: 0,
|
||||
right: uint32(a.Region.Max.X),
|
||||
bottom: uint32(a.Region.Max.Y),
|
||||
back: 1,
|
||||
}, unsafe.Pointer(&a.Pixels[0]), uint32(4*a.Region.Dx()), 0)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *image11) setAsRenderTarget(useStencil bool) error {
|
||||
if i.renderTargetView == nil {
|
||||
rtv, err := i.graphics.device.CreateRenderTargetView(unsafe.Pointer(i.texture), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.renderTargetView = rtv
|
||||
}
|
||||
|
||||
if !useStencil {
|
||||
i.graphics.deviceContext.OMSetRenderTargets([]*_ID3D11RenderTargetView{i.renderTargetView}, nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
if i.screen {
|
||||
return fmt.Errorf("directx: a stencil buffer is not available for a screen image")
|
||||
}
|
||||
|
||||
if i.stencil == nil {
|
||||
w, h := i.internalSize()
|
||||
s, err := i.graphics.device.CreateTexture2D(&_D3D11_TEXTURE2D_DESC{
|
||||
Width: uint32(w),
|
||||
Height: uint32(h),
|
||||
MipLevels: 0,
|
||||
ArraySize: 1,
|
||||
Format: _DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||
SampleDesc: _DXGI_SAMPLE_DESC{
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
Usage: _D3D11_USAGE_DEFAULT,
|
||||
BindFlags: uint32(_D3D11_BIND_DEPTH_STENCIL),
|
||||
CPUAccessFlags: 0,
|
||||
MiscFlags: 0,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.stencil = s
|
||||
}
|
||||
|
||||
if i.stencilView == nil {
|
||||
sv, err := i.graphics.device.CreateDepthStencilView(unsafe.Pointer(i.stencil), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.stencilView = sv
|
||||
}
|
||||
|
||||
i.graphics.deviceContext.OMSetRenderTargets([]*_ID3D11RenderTargetView{i.renderTargetView}, i.stencilView)
|
||||
i.graphics.deviceContext.ClearDepthStencilView(i.stencilView, uint8(_D3D11_CLEAR_STENCIL), 0, 0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *image11) getShaderResourceView() (*_ID3D11ShaderResourceView, error) {
|
||||
if i.shaderResourceView == nil {
|
||||
srv, err := i.graphics.device.CreateShaderResourceView(unsafe.Pointer(i.texture), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i.shaderResourceView = srv
|
||||
}
|
||||
return i.shaderResourceView, nil
|
||||
}
|
||||
Generated
Vendored
+426
@@ -0,0 +1,426 @@
|
||||
// Copyright 2023 The Ebitengine Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package directx
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"image"
|
||||
"unsafe"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
)
|
||||
|
||||
type image12 struct {
|
||||
graphics *graphics12
|
||||
id graphicsdriver.ImageID
|
||||
width int
|
||||
height int
|
||||
screen bool
|
||||
|
||||
states [frameCount]_D3D12_RESOURCE_STATES
|
||||
texture *_ID3D12Resource
|
||||
stencil *_ID3D12Resource
|
||||
rtvDescriptorHeap *_ID3D12DescriptorHeap
|
||||
dsvDescriptorHeap *_ID3D12DescriptorHeap
|
||||
|
||||
uploadingStagingBuffers []*_ID3D12Resource
|
||||
}
|
||||
|
||||
func (i *image12) ID() graphicsdriver.ImageID {
|
||||
return i.id
|
||||
}
|
||||
|
||||
func (i *image12) Dispose() {
|
||||
// Dipose the images later as this image might still be used.
|
||||
i.graphics.removeImage(i)
|
||||
}
|
||||
|
||||
func (i *image12) disposeImpl() {
|
||||
if i.dsvDescriptorHeap != nil {
|
||||
i.dsvDescriptorHeap.Release()
|
||||
i.dsvDescriptorHeap = nil
|
||||
}
|
||||
if i.rtvDescriptorHeap != nil {
|
||||
i.rtvDescriptorHeap.Release()
|
||||
i.rtvDescriptorHeap = nil
|
||||
}
|
||||
if i.stencil != nil {
|
||||
i.stencil.Release()
|
||||
i.stencil = nil
|
||||
}
|
||||
if i.texture != nil {
|
||||
i.texture.Release()
|
||||
i.texture = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (i *image12) ReadPixels(args []graphicsdriver.PixelsArgs) error {
|
||||
if i.screen {
|
||||
return errors.New("directx: Pixels cannot be called on the screen")
|
||||
}
|
||||
|
||||
if err := i.graphics.flushCommandList(i.graphics.drawCommandList); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var unionRegion image.Rectangle
|
||||
for _, a := range args {
|
||||
unionRegion = unionRegion.Union(a.Region)
|
||||
}
|
||||
|
||||
desc := _D3D12_RESOURCE_DESC{
|
||||
Dimension: _D3D12_RESOURCE_DIMENSION_TEXTURE2D,
|
||||
Alignment: 0,
|
||||
Width: uint64(unionRegion.Dx()),
|
||||
Height: uint32(unionRegion.Dy()),
|
||||
DepthOrArraySize: 1,
|
||||
MipLevels: 0,
|
||||
Format: _DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
SampleDesc: _DXGI_SAMPLE_DESC{
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
Layout: _D3D12_TEXTURE_LAYOUT_UNKNOWN,
|
||||
Flags: _D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
|
||||
}
|
||||
layouts, _, _, totalBytes := i.graphics.device.GetCopyableFootprints(&desc, 0, 1, 0)
|
||||
readingStagingBuffer, err := createBuffer(i.graphics.device, totalBytes, _D3D12_HEAP_TYPE_READBACK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
readingStagingBuffer.Release()
|
||||
}()
|
||||
|
||||
if rb, ok := i.transiteState(_D3D12_RESOURCE_STATE_COPY_SOURCE); ok {
|
||||
i.graphics.copyCommandList.ResourceBarrier([]_D3D12_RESOURCE_BARRIER_Transition{rb})
|
||||
}
|
||||
|
||||
m, err := readingStagingBuffer.Map(0, &_D3D12_RANGE{0, 0})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dst := _D3D12_TEXTURE_COPY_LOCATION_PlacedFootPrint{
|
||||
pResource: readingStagingBuffer,
|
||||
Type: _D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
|
||||
PlacedFootprint: layouts,
|
||||
}
|
||||
src := _D3D12_TEXTURE_COPY_LOCATION_SubresourceIndex{
|
||||
pResource: i.texture,
|
||||
Type: _D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
|
||||
SubresourceIndex: 0,
|
||||
}
|
||||
i.graphics.needFlushCopyCommandList = true
|
||||
i.graphics.copyCommandList.CopyTextureRegion_PlacedFootPrint_SubresourceIndex(
|
||||
&dst, 0, 0, 0, &src, &_D3D12_BOX{
|
||||
left: uint32(unionRegion.Min.X),
|
||||
top: uint32(unionRegion.Min.Y),
|
||||
front: 0,
|
||||
right: uint32(unionRegion.Max.X),
|
||||
bottom: uint32(unionRegion.Max.Y),
|
||||
back: 1,
|
||||
})
|
||||
|
||||
if err := i.graphics.flushCommandList(i.graphics.copyCommandList); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stride := int(layouts.Footprint.RowPitch)
|
||||
srcPix := unsafe.Slice((*byte)(unsafe.Pointer(m)), totalBytes)
|
||||
for _, a := range args {
|
||||
w := a.Region.Dx()
|
||||
if unionRegion == a.Region && stride == 4*w {
|
||||
copy(a.Pixels, srcPix)
|
||||
continue
|
||||
}
|
||||
offset := 4*(a.Region.Min.X-unionRegion.Min.X) + stride*(a.Region.Min.Y-unionRegion.Min.Y)
|
||||
for j := 0; j < a.Region.Dy(); j++ {
|
||||
copy(a.Pixels[j*w*4:(j+1)*w*4], srcPix[offset+j*stride:])
|
||||
}
|
||||
}
|
||||
|
||||
readingStagingBuffer.Unmap(0, nil)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *image12) WritePixels(args []graphicsdriver.PixelsArgs) error {
|
||||
if i.screen {
|
||||
return errors.New("directx: WritePixels cannot be called on the screen")
|
||||
}
|
||||
|
||||
if err := i.graphics.flushCommandList(i.graphics.drawCommandList); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var region image.Rectangle
|
||||
for _, a := range args {
|
||||
region = region.Union(a.Region)
|
||||
}
|
||||
|
||||
desc := _D3D12_RESOURCE_DESC{
|
||||
Dimension: _D3D12_RESOURCE_DIMENSION_TEXTURE2D,
|
||||
Alignment: 0,
|
||||
Width: uint64(region.Dx()),
|
||||
Height: uint32(region.Dy()),
|
||||
DepthOrArraySize: 1,
|
||||
MipLevels: 0,
|
||||
Format: _DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
SampleDesc: _DXGI_SAMPLE_DESC{
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
Layout: _D3D12_TEXTURE_LAYOUT_UNKNOWN,
|
||||
Flags: _D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
|
||||
}
|
||||
layouts, _, _, totalBytes := i.graphics.device.GetCopyableFootprints(&desc, 0, 1, 0)
|
||||
uploadingStagingBuffer, err := createBuffer(i.graphics.device, totalBytes, _D3D12_HEAP_TYPE_UPLOAD)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.uploadingStagingBuffers = append(i.uploadingStagingBuffers, uploadingStagingBuffer)
|
||||
|
||||
if rb, ok := i.transiteState(_D3D12_RESOURCE_STATE_COPY_DEST); ok {
|
||||
i.graphics.copyCommandList.ResourceBarrier([]_D3D12_RESOURCE_BARRIER_Transition{rb})
|
||||
}
|
||||
|
||||
m, err := uploadingStagingBuffer.Map(0, &_D3D12_RANGE{0, 0})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i.graphics.needFlushCopyCommandList = true
|
||||
|
||||
srcBytes := unsafe.Slice((*byte)(unsafe.Pointer(m)), totalBytes)
|
||||
for _, a := range args {
|
||||
for j := 0; j < a.Region.Dy(); j++ {
|
||||
copy(srcBytes[((a.Region.Min.Y-region.Min.Y)+j)*int(layouts.Footprint.RowPitch)+(a.Region.Min.X-region.Min.X)*4:], a.Pixels[j*a.Region.Dx()*4:(j+1)*a.Region.Dx()*4])
|
||||
}
|
||||
}
|
||||
|
||||
for _, a := range args {
|
||||
dst := _D3D12_TEXTURE_COPY_LOCATION_SubresourceIndex{
|
||||
pResource: i.texture,
|
||||
Type: _D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
|
||||
SubresourceIndex: 0,
|
||||
}
|
||||
src := _D3D12_TEXTURE_COPY_LOCATION_PlacedFootPrint{
|
||||
pResource: uploadingStagingBuffer,
|
||||
Type: _D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
|
||||
PlacedFootprint: layouts,
|
||||
}
|
||||
i.graphics.copyCommandList.CopyTextureRegion_SubresourceIndex_PlacedFootPrint(
|
||||
&dst, uint32(a.Region.Min.X), uint32(a.Region.Min.Y), 0, &src, &_D3D12_BOX{
|
||||
left: uint32(a.Region.Min.X - region.Min.X),
|
||||
top: uint32(a.Region.Min.Y - region.Min.Y),
|
||||
front: 0,
|
||||
right: uint32(a.Region.Max.X - region.Min.X),
|
||||
bottom: uint32(a.Region.Max.Y - region.Min.Y),
|
||||
back: 1,
|
||||
})
|
||||
}
|
||||
|
||||
uploadingStagingBuffer.Unmap(0, nil)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *image12) resource() *_ID3D12Resource {
|
||||
if i.screen {
|
||||
return i.graphics.renderTargets[i.graphics.frameIndex]
|
||||
}
|
||||
return i.texture
|
||||
}
|
||||
|
||||
func (i *image12) state() _D3D12_RESOURCE_STATES {
|
||||
if i.screen {
|
||||
return i.states[i.graphics.frameIndex]
|
||||
}
|
||||
return i.states[0]
|
||||
}
|
||||
|
||||
func (i *image12) setState(newState _D3D12_RESOURCE_STATES) {
|
||||
if i.screen {
|
||||
i.states[i.graphics.frameIndex] = newState
|
||||
return
|
||||
}
|
||||
i.states[0] = newState
|
||||
}
|
||||
|
||||
func (i *image12) transiteState(newState _D3D12_RESOURCE_STATES) (_D3D12_RESOURCE_BARRIER_Transition, bool) {
|
||||
if i.state() == newState {
|
||||
return _D3D12_RESOURCE_BARRIER_Transition{}, false
|
||||
}
|
||||
oldState := i.state()
|
||||
i.setState(newState)
|
||||
|
||||
return _D3D12_RESOURCE_BARRIER_Transition{
|
||||
Type: _D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
|
||||
Flags: _D3D12_RESOURCE_BARRIER_FLAG_NONE,
|
||||
Transition: _D3D12_RESOURCE_TRANSITION_BARRIER{
|
||||
pResource: i.resource(),
|
||||
Subresource: _D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
|
||||
StateBefore: oldState,
|
||||
StateAfter: newState,
|
||||
},
|
||||
}, true
|
||||
}
|
||||
|
||||
func (i *image12) internalSize() (int, int) {
|
||||
if i.screen {
|
||||
return i.width, i.height
|
||||
}
|
||||
return graphics.InternalImageSize(i.width), graphics.InternalImageSize(i.height)
|
||||
}
|
||||
|
||||
func (i *image12) setAsRenderTarget(drawCommandList *_ID3D12GraphicsCommandList, device *_ID3D12Device, useStencil bool) error {
|
||||
if err := i.ensureRenderTargetView(device); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if i.screen {
|
||||
if useStencil {
|
||||
return fmt.Errorf("directx: stencils are not available on the screen framebuffer")
|
||||
}
|
||||
rtv, err := i.graphics.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rtv.Offset(int32(i.graphics.frameIndex), i.graphics.rtvDescriptorSize)
|
||||
drawCommandList.OMSetRenderTargets([]_D3D12_CPU_DESCRIPTOR_HANDLE{rtv}, false, nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
rtv, err := i.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !useStencil {
|
||||
drawCommandList.OMSetRenderTargets([]_D3D12_CPU_DESCRIPTOR_HANDLE{rtv}, false, nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := i.ensureDepthStencilView(device); err != nil {
|
||||
return err
|
||||
}
|
||||
dsv, err := i.dsvDescriptorHeap.GetCPUDescriptorHandleForHeapStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
drawCommandList.OMSetStencilRef(0)
|
||||
drawCommandList.OMSetRenderTargets([]_D3D12_CPU_DESCRIPTOR_HANDLE{rtv}, false, &dsv)
|
||||
drawCommandList.ClearDepthStencilView(dsv, _D3D12_CLEAR_FLAG_STENCIL, 0, 0, nil)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *image12) ensureRenderTargetView(device *_ID3D12Device) error {
|
||||
if i.screen {
|
||||
return nil
|
||||
}
|
||||
|
||||
if i.rtvDescriptorHeap != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
h, err := device.CreateDescriptorHeap(&_D3D12_DESCRIPTOR_HEAP_DESC{
|
||||
Type: _D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
|
||||
NumDescriptors: 1,
|
||||
Flags: _D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
|
||||
NodeMask: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.rtvDescriptorHeap = h
|
||||
|
||||
rtv, err := i.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
device.CreateRenderTargetView(i.texture, nil, rtv)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *image12) ensureDepthStencilView(device *_ID3D12Device) error {
|
||||
if i.screen {
|
||||
return fmt.Errorf("directx: stencils are not available on the screen framebuffer")
|
||||
}
|
||||
|
||||
if i.dsvDescriptorHeap != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
h, err := device.CreateDescriptorHeap(&_D3D12_DESCRIPTOR_HEAP_DESC{
|
||||
Type: _D3D12_DESCRIPTOR_HEAP_TYPE_DSV,
|
||||
NumDescriptors: 1,
|
||||
Flags: _D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
|
||||
NodeMask: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.dsvDescriptorHeap = h
|
||||
|
||||
dsv, err := i.dsvDescriptorHeap.GetCPUDescriptorHandleForHeapStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if i.stencil == nil {
|
||||
s, err := device.CreateCommittedResource(&_D3D12_HEAP_PROPERTIES{
|
||||
Type: _D3D12_HEAP_TYPE_DEFAULT,
|
||||
CPUPageProperty: _D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
|
||||
MemoryPoolPreference: _D3D12_MEMORY_POOL_UNKNOWN,
|
||||
CreationNodeMask: 1,
|
||||
VisibleNodeMask: 1,
|
||||
}, _D3D12_HEAP_FLAG_NONE, &_D3D12_RESOURCE_DESC{
|
||||
Dimension: _D3D12_RESOURCE_DIMENSION_TEXTURE2D,
|
||||
Alignment: 0,
|
||||
Width: uint64(graphics.InternalImageSize(i.width)),
|
||||
Height: uint32(graphics.InternalImageSize(i.height)),
|
||||
DepthOrArraySize: 1,
|
||||
MipLevels: 0,
|
||||
Format: _DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||
SampleDesc: _DXGI_SAMPLE_DESC{
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
Layout: _D3D12_TEXTURE_LAYOUT_UNKNOWN,
|
||||
Flags: _D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL,
|
||||
}, _D3D12_RESOURCE_STATE_DEPTH_WRITE, &_D3D12_CLEAR_VALUE{
|
||||
Format: _DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.stencil = s
|
||||
}
|
||||
device.CreateDepthStencilView(i.stencil, nil, dsv)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *image12) releaseUploadingStagingBuffers() {
|
||||
for idx, buf := range i.uploadingStagingBuffers {
|
||||
buf.Release()
|
||||
i.uploadingStagingBuffers[idx] = nil
|
||||
}
|
||||
i.uploadingStagingBuffers = i.uploadingStagingBuffers[:0]
|
||||
}
|
||||
Generated
Vendored
+567
@@ -0,0 +1,567 @@
|
||||
// Copyright 2022 The Ebiten Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package directx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"unsafe"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
)
|
||||
|
||||
var inputElementDescsForDX12 = []_D3D12_INPUT_ELEMENT_DESC{
|
||||
{
|
||||
SemanticName: &([]byte("POSITION\000"))[0],
|
||||
SemanticIndex: 0,
|
||||
Format: _DXGI_FORMAT_R32G32_FLOAT,
|
||||
InputSlot: 0,
|
||||
AlignedByteOffset: _D3D12_APPEND_ALIGNED_ELEMENT,
|
||||
InputSlotClass: _D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
|
||||
InstanceDataStepRate: 0,
|
||||
},
|
||||
{
|
||||
SemanticName: &([]byte("TEXCOORD\000"))[0],
|
||||
SemanticIndex: 0,
|
||||
Format: _DXGI_FORMAT_R32G32_FLOAT,
|
||||
InputSlot: 0,
|
||||
AlignedByteOffset: _D3D12_APPEND_ALIGNED_ELEMENT,
|
||||
InputSlotClass: _D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
|
||||
InstanceDataStepRate: 0,
|
||||
},
|
||||
{
|
||||
SemanticName: &([]byte("COLOR\000"))[0],
|
||||
SemanticIndex: 0,
|
||||
Format: _DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||
InputSlot: 0,
|
||||
AlignedByteOffset: _D3D12_APPEND_ALIGNED_ELEMENT,
|
||||
InputSlotClass: _D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
|
||||
InstanceDataStepRate: 0,
|
||||
},
|
||||
}
|
||||
|
||||
const numDescriptorsPerFrame = 32
|
||||
|
||||
func blendFactorToBlend12(f graphicsdriver.BlendFactor, alpha bool) _D3D12_BLEND {
|
||||
// D3D12_RENDER_TARGET_BLEND_DESC's *BlendAlpha members don't allow *_COLOR values.
|
||||
// See https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_render_target_blend_desc.
|
||||
|
||||
switch f {
|
||||
case graphicsdriver.BlendFactorZero:
|
||||
return _D3D12_BLEND_ZERO
|
||||
case graphicsdriver.BlendFactorOne:
|
||||
return _D3D12_BLEND_ONE
|
||||
case graphicsdriver.BlendFactorSourceColor:
|
||||
if alpha {
|
||||
return _D3D12_BLEND_SRC_ALPHA
|
||||
}
|
||||
return _D3D12_BLEND_SRC_COLOR
|
||||
case graphicsdriver.BlendFactorOneMinusSourceColor:
|
||||
if alpha {
|
||||
return _D3D12_BLEND_INV_SRC_ALPHA
|
||||
}
|
||||
return _D3D12_BLEND_INV_SRC_COLOR
|
||||
case graphicsdriver.BlendFactorSourceAlpha:
|
||||
return _D3D12_BLEND_SRC_ALPHA
|
||||
case graphicsdriver.BlendFactorOneMinusSourceAlpha:
|
||||
return _D3D12_BLEND_INV_SRC_ALPHA
|
||||
case graphicsdriver.BlendFactorDestinationColor:
|
||||
if alpha {
|
||||
return _D3D12_BLEND_DEST_ALPHA
|
||||
}
|
||||
return _D3D12_BLEND_DEST_COLOR
|
||||
case graphicsdriver.BlendFactorOneMinusDestinationColor:
|
||||
if alpha {
|
||||
return _D3D12_BLEND_INV_DEST_ALPHA
|
||||
}
|
||||
return _D3D12_BLEND_INV_DEST_COLOR
|
||||
case graphicsdriver.BlendFactorDestinationAlpha:
|
||||
return _D3D12_BLEND_DEST_ALPHA
|
||||
case graphicsdriver.BlendFactorOneMinusDestinationAlpha:
|
||||
return _D3D12_BLEND_INV_DEST_ALPHA
|
||||
case graphicsdriver.BlendFactorSourceAlphaSaturated:
|
||||
return _D3D12_BLEND_SRC_ALPHA_SAT
|
||||
default:
|
||||
panic(fmt.Sprintf("directx: invalid blend factor: %d", f))
|
||||
}
|
||||
}
|
||||
|
||||
func blendOperationToBlendOp12(o graphicsdriver.BlendOperation) _D3D12_BLEND_OP {
|
||||
switch o {
|
||||
case graphicsdriver.BlendOperationAdd:
|
||||
return _D3D12_BLEND_OP_ADD
|
||||
case graphicsdriver.BlendOperationSubtract:
|
||||
return _D3D12_BLEND_OP_SUBTRACT
|
||||
case graphicsdriver.BlendOperationReverseSubtract:
|
||||
return _D3D12_BLEND_OP_REV_SUBTRACT
|
||||
case graphicsdriver.BlendOperationMin:
|
||||
return _D3D12_BLEND_OP_MIN
|
||||
case graphicsdriver.BlendOperationMax:
|
||||
return _D3D12_BLEND_OP_MAX
|
||||
default:
|
||||
panic(fmt.Sprintf("directx: invalid blend operation: %d", o))
|
||||
}
|
||||
}
|
||||
|
||||
type pipelineStates struct {
|
||||
rootSignature *_ID3D12RootSignature
|
||||
|
||||
shaderDescriptorHeap *_ID3D12DescriptorHeap
|
||||
shaderDescriptorSize uint32
|
||||
|
||||
samplerDescriptorHeap *_ID3D12DescriptorHeap
|
||||
|
||||
constantBuffers [frameCount][]*_ID3D12Resource
|
||||
constantBufferMaps [frameCount][]uintptr
|
||||
}
|
||||
|
||||
const numConstantBufferAndSourceTextures = 1 + graphics.ShaderImageCount
|
||||
|
||||
func (p *pipelineStates) initialize(device *_ID3D12Device) (ferr error) {
|
||||
// Create a CBV/SRV/UAV descriptor heap.
|
||||
// 5n+0: constants
|
||||
// 5n+m (1<=4): textures
|
||||
shaderH, err := device.CreateDescriptorHeap(&_D3D12_DESCRIPTOR_HEAP_DESC{
|
||||
Type: _D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
||||
NumDescriptors: frameCount * numDescriptorsPerFrame * numConstantBufferAndSourceTextures,
|
||||
Flags: _D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
|
||||
NodeMask: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.shaderDescriptorHeap = shaderH
|
||||
defer func() {
|
||||
if ferr != nil {
|
||||
p.shaderDescriptorHeap.Release()
|
||||
p.shaderDescriptorHeap = nil
|
||||
}
|
||||
}()
|
||||
p.shaderDescriptorSize = device.GetDescriptorHandleIncrementSize(_D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
|
||||
|
||||
samplerH, err := device.CreateDescriptorHeap(&_D3D12_DESCRIPTOR_HEAP_DESC{
|
||||
Type: _D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
|
||||
NumDescriptors: 1,
|
||||
Flags: _D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
|
||||
NodeMask: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.samplerDescriptorHeap = samplerH
|
||||
|
||||
h, err := p.samplerDescriptorHeap.GetCPUDescriptorHandleForHeapStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
device.CreateSampler(&_D3D12_SAMPLER_DESC{
|
||||
Filter: _D3D12_FILTER_MIN_MAG_MIP_POINT,
|
||||
AddressU: _D3D12_TEXTURE_ADDRESS_MODE_WRAP,
|
||||
AddressV: _D3D12_TEXTURE_ADDRESS_MODE_WRAP,
|
||||
AddressW: _D3D12_TEXTURE_ADDRESS_MODE_WRAP,
|
||||
ComparisonFunc: _D3D12_COMPARISON_FUNC_NEVER,
|
||||
MinLOD: -math.MaxFloat32,
|
||||
MaxLOD: math.MaxFloat32,
|
||||
}, h)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *pipelineStates) drawTriangles(device *_ID3D12Device, commandList *_ID3D12GraphicsCommandList, frameIndex int, screen bool, srcs [graphics.ShaderImageCount]*image12, shader *shader12, dstRegions []graphicsdriver.DstRegion, uniforms []uint32, blend graphicsdriver.Blend, indexOffset int, fillRule graphicsdriver.FillRule) error {
|
||||
idx := len(p.constantBuffers[frameIndex])
|
||||
if idx >= numDescriptorsPerFrame {
|
||||
return fmt.Errorf("directx: too many constant buffers")
|
||||
}
|
||||
|
||||
if cap(p.constantBuffers[frameIndex]) > idx {
|
||||
p.constantBuffers[frameIndex] = p.constantBuffers[frameIndex][:idx+1]
|
||||
p.constantBufferMaps[frameIndex] = p.constantBufferMaps[frameIndex][:idx+1]
|
||||
} else {
|
||||
p.constantBuffers[frameIndex] = append(p.constantBuffers[frameIndex], nil)
|
||||
p.constantBufferMaps[frameIndex] = append(p.constantBufferMaps[frameIndex], 0)
|
||||
}
|
||||
|
||||
const bufferSizeAlignment = 256
|
||||
bufferSize := uint32(unsafe.Sizeof(uint32(0))) * uint32(len(uniforms))
|
||||
if bufferSize > 0 {
|
||||
bufferSize = ((bufferSize-1)/bufferSizeAlignment + 1) * bufferSizeAlignment
|
||||
}
|
||||
|
||||
cb := p.constantBuffers[frameIndex][idx]
|
||||
m := p.constantBufferMaps[frameIndex][idx]
|
||||
if cb != nil {
|
||||
if uint32(cb.GetDesc().Width) < bufferSize {
|
||||
p.constantBuffers[frameIndex][idx].Unmap(0, nil)
|
||||
p.constantBuffers[frameIndex][idx].Release()
|
||||
p.constantBuffers[frameIndex][idx] = nil
|
||||
p.constantBufferMaps[frameIndex][idx] = 0
|
||||
cb = nil
|
||||
}
|
||||
}
|
||||
if cb == nil {
|
||||
var err error
|
||||
cb, err = createBuffer(device, uint64(bufferSize), _D3D12_HEAP_TYPE_UPLOAD)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.constantBuffers[frameIndex][idx] = cb
|
||||
|
||||
h, err := p.shaderDescriptorHeap.GetCPUDescriptorHandleForHeapStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
offset := int32(numConstantBufferAndSourceTextures * (frameIndex*numDescriptorsPerFrame + idx))
|
||||
h.Offset(offset, p.shaderDescriptorSize)
|
||||
device.CreateConstantBufferView(&_D3D12_CONSTANT_BUFFER_VIEW_DESC{
|
||||
BufferLocation: cb.GetGPUVirtualAddress(),
|
||||
SizeInBytes: bufferSize,
|
||||
}, h)
|
||||
|
||||
m, err = cb.Map(0, &_D3D12_RANGE{0, 0})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.constantBufferMaps[frameIndex][idx] = m
|
||||
}
|
||||
if m == 0 {
|
||||
return fmt.Errorf("directx: ID3D12Resource::Map failed")
|
||||
}
|
||||
|
||||
h, err := p.shaderDescriptorHeap.GetCPUDescriptorHandleForHeapStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
offset := int32(numConstantBufferAndSourceTextures * (frameIndex*numDescriptorsPerFrame + idx))
|
||||
h.Offset(offset, p.shaderDescriptorSize)
|
||||
for _, src := range srcs {
|
||||
h.Offset(1, p.shaderDescriptorSize)
|
||||
if src == nil {
|
||||
continue
|
||||
}
|
||||
device.CreateShaderResourceView(src.resource(), &_D3D12_SHADER_RESOURCE_VIEW_DESC{
|
||||
Format: _DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
ViewDimension: _D3D12_SRV_DIMENSION_TEXTURE2D,
|
||||
Shader4ComponentMapping: _D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
|
||||
Texture2D: _D3D12_TEX2D_SRV{
|
||||
MipLevels: 1, // TODO: Can this be 0?
|
||||
},
|
||||
}, h)
|
||||
}
|
||||
|
||||
// Update the constant buffer.
|
||||
copy(unsafe.Slice((*uint32)(unsafe.Pointer(m)), len(uniforms)), uniforms)
|
||||
|
||||
rs, err := p.ensureRootSignature(device)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
commandList.SetGraphicsRootSignature(rs)
|
||||
|
||||
commandList.SetDescriptorHeaps([]*_ID3D12DescriptorHeap{
|
||||
p.shaderDescriptorHeap,
|
||||
p.samplerDescriptorHeap,
|
||||
})
|
||||
|
||||
// Match the indices with rootParams in graphicsPipelineState.
|
||||
gh, err := p.shaderDescriptorHeap.GetGPUDescriptorHandleForHeapStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gh.Offset(offset, p.shaderDescriptorSize)
|
||||
commandList.SetGraphicsRootDescriptorTable(0, gh)
|
||||
commandList.SetGraphicsRootDescriptorTable(1, gh)
|
||||
sh, err := p.samplerDescriptorHeap.GetGPUDescriptorHandleForHeapStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
commandList.SetGraphicsRootDescriptorTable(2, sh)
|
||||
|
||||
if fillRule == graphicsdriver.FillAll {
|
||||
s, err := shader.pipelineState(blend, noStencil, screen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
commandList.SetPipelineState(s)
|
||||
}
|
||||
|
||||
for _, dstRegion := range dstRegions {
|
||||
commandList.RSSetScissorRects([]_D3D12_RECT{
|
||||
{
|
||||
left: int32(dstRegion.Region.Min.X),
|
||||
top: int32(dstRegion.Region.Min.Y),
|
||||
right: int32(dstRegion.Region.Max.X),
|
||||
bottom: int32(dstRegion.Region.Max.Y),
|
||||
},
|
||||
})
|
||||
switch fillRule {
|
||||
case graphicsdriver.FillAll:
|
||||
commandList.DrawIndexedInstanced(uint32(dstRegion.IndexCount), 1, uint32(indexOffset), 0, 0)
|
||||
case graphicsdriver.NonZero:
|
||||
s, err := shader.pipelineState(blend, incrementStencil, screen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
commandList.SetPipelineState(s)
|
||||
commandList.DrawIndexedInstanced(uint32(dstRegion.IndexCount), 1, uint32(indexOffset), 0, 0)
|
||||
case graphicsdriver.EvenOdd:
|
||||
s, err := shader.pipelineState(blend, invertStencil, screen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
commandList.SetPipelineState(s)
|
||||
commandList.DrawIndexedInstanced(uint32(dstRegion.IndexCount), 1, uint32(indexOffset), 0, 0)
|
||||
}
|
||||
|
||||
if fillRule != graphicsdriver.FillAll {
|
||||
s, err := shader.pipelineState(blend, drawWithStencil, screen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
commandList.SetPipelineState(s)
|
||||
commandList.DrawIndexedInstanced(uint32(dstRegion.IndexCount), 1, uint32(indexOffset), 0, 0)
|
||||
}
|
||||
|
||||
indexOffset += dstRegion.IndexCount
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *pipelineStates) ensureRootSignature(device *_ID3D12Device) (rootSignature *_ID3D12RootSignature, ferr error) {
|
||||
if p.rootSignature != nil {
|
||||
return p.rootSignature, nil
|
||||
}
|
||||
|
||||
cbv := _D3D12_DESCRIPTOR_RANGE{
|
||||
RangeType: _D3D12_DESCRIPTOR_RANGE_TYPE_CBV, // b0
|
||||
NumDescriptors: 1,
|
||||
BaseShaderRegister: 0,
|
||||
RegisterSpace: 0,
|
||||
OffsetInDescriptorsFromTableStart: 0,
|
||||
}
|
||||
srv := _D3D12_DESCRIPTOR_RANGE{
|
||||
RangeType: _D3D12_DESCRIPTOR_RANGE_TYPE_SRV, // t0
|
||||
NumDescriptors: graphics.ShaderImageCount,
|
||||
BaseShaderRegister: 0,
|
||||
RegisterSpace: 0,
|
||||
OffsetInDescriptorsFromTableStart: 1,
|
||||
}
|
||||
sampler := _D3D12_DESCRIPTOR_RANGE{
|
||||
RangeType: _D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, // s0
|
||||
NumDescriptors: 1,
|
||||
BaseShaderRegister: 0,
|
||||
RegisterSpace: 0,
|
||||
OffsetInDescriptorsFromTableStart: 0,
|
||||
}
|
||||
|
||||
rootParams := [...]_D3D12_ROOT_PARAMETER{
|
||||
{
|
||||
ParameterType: _D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE,
|
||||
DescriptorTable: _D3D12_ROOT_DESCRIPTOR_TABLE{
|
||||
NumDescriptorRanges: 1,
|
||||
pDescriptorRanges: &cbv,
|
||||
},
|
||||
ShaderVisibility: _D3D12_SHADER_VISIBILITY_ALL,
|
||||
},
|
||||
{
|
||||
ParameterType: _D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE,
|
||||
DescriptorTable: _D3D12_ROOT_DESCRIPTOR_TABLE{
|
||||
NumDescriptorRanges: 1,
|
||||
pDescriptorRanges: &srv,
|
||||
},
|
||||
ShaderVisibility: _D3D12_SHADER_VISIBILITY_PIXEL,
|
||||
},
|
||||
{
|
||||
ParameterType: _D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE,
|
||||
DescriptorTable: _D3D12_ROOT_DESCRIPTOR_TABLE{
|
||||
NumDescriptorRanges: 1,
|
||||
pDescriptorRanges: &sampler,
|
||||
},
|
||||
ShaderVisibility: _D3D12_SHADER_VISIBILITY_PIXEL,
|
||||
},
|
||||
}
|
||||
|
||||
// Create a root signature.
|
||||
sig, err := _D3D12SerializeRootSignature(&_D3D12_ROOT_SIGNATURE_DESC{
|
||||
NumParameters: uint32(len(rootParams)),
|
||||
pParameters: &rootParams[0],
|
||||
NumStaticSamplers: 0,
|
||||
pStaticSamplers: nil,
|
||||
Flags: _D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT,
|
||||
}, _D3D_ROOT_SIGNATURE_VERSION_1_0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer sig.Release()
|
||||
|
||||
rs, err := device.CreateRootSignature(0, sig.GetBufferPointer(), sig.GetBufferSize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if ferr != nil {
|
||||
rootSignature.Release()
|
||||
}
|
||||
}()
|
||||
|
||||
p.rootSignature = rs
|
||||
|
||||
return p.rootSignature, nil
|
||||
}
|
||||
|
||||
func (p *pipelineStates) newPipelineState(device *_ID3D12Device, vsh, psh *_ID3DBlob, blend graphicsdriver.Blend, stencilMode stencilMode, screen bool) (state *_ID3D12PipelineState, ferr error) {
|
||||
rootSignature, err := p.ensureRootSignature(device)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if ferr != nil {
|
||||
rootSignature.Release()
|
||||
}
|
||||
}()
|
||||
|
||||
depthStencilDesc := _D3D12_DEPTH_STENCIL_DESC{
|
||||
DepthEnable: 0,
|
||||
DepthWriteMask: _D3D12_DEPTH_WRITE_MASK_ALL,
|
||||
DepthFunc: _D3D12_COMPARISON_FUNC_LESS,
|
||||
StencilEnable: 0,
|
||||
StencilReadMask: _D3D12_DEFAULT_STENCIL_READ_MASK,
|
||||
StencilWriteMask: _D3D12_DEFAULT_STENCIL_WRITE_MASK,
|
||||
FrontFace: _D3D12_DEPTH_STENCILOP_DESC{
|
||||
StencilFailOp: _D3D12_STENCIL_OP_KEEP,
|
||||
StencilDepthFailOp: _D3D12_STENCIL_OP_KEEP,
|
||||
StencilPassOp: _D3D12_STENCIL_OP_KEEP,
|
||||
StencilFunc: _D3D12_COMPARISON_FUNC_ALWAYS,
|
||||
},
|
||||
BackFace: _D3D12_DEPTH_STENCILOP_DESC{
|
||||
StencilFailOp: _D3D12_STENCIL_OP_KEEP,
|
||||
StencilDepthFailOp: _D3D12_STENCIL_OP_KEEP,
|
||||
StencilPassOp: _D3D12_STENCIL_OP_KEEP,
|
||||
StencilFunc: _D3D12_COMPARISON_FUNC_ALWAYS,
|
||||
},
|
||||
}
|
||||
|
||||
var writeMask uint8
|
||||
if stencilMode == noStencil || stencilMode == drawWithStencil {
|
||||
writeMask = uint8(_D3D12_COLOR_WRITE_ENABLE_ALL)
|
||||
}
|
||||
|
||||
switch stencilMode {
|
||||
case incrementStencil:
|
||||
depthStencilDesc.StencilEnable = 1
|
||||
depthStencilDesc.FrontFace.StencilPassOp = _D3D12_STENCIL_OP_INCR
|
||||
depthStencilDesc.BackFace.StencilPassOp = _D3D12_STENCIL_OP_DECR
|
||||
case invertStencil:
|
||||
depthStencilDesc.StencilEnable = 1
|
||||
depthStencilDesc.FrontFace.StencilPassOp = _D3D12_STENCIL_OP_INVERT
|
||||
depthStencilDesc.BackFace.StencilPassOp = _D3D12_STENCIL_OP_INVERT
|
||||
case drawWithStencil:
|
||||
depthStencilDesc.StencilEnable = 1
|
||||
depthStencilDesc.FrontFace.StencilFunc = _D3D12_COMPARISON_FUNC_NOT_EQUAL
|
||||
depthStencilDesc.BackFace.StencilFunc = _D3D12_COMPARISON_FUNC_NOT_EQUAL
|
||||
}
|
||||
|
||||
rtvFormat := _DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
if screen {
|
||||
rtvFormat = _DXGI_FORMAT_B8G8R8A8_UNORM
|
||||
}
|
||||
dsvFormat := _DXGI_FORMAT_UNKNOWN
|
||||
if stencilMode != noStencil {
|
||||
dsvFormat = _DXGI_FORMAT_D24_UNORM_S8_UINT
|
||||
}
|
||||
|
||||
// Create a pipeline state.
|
||||
psoDesc := _D3D12_GRAPHICS_PIPELINE_STATE_DESC{
|
||||
pRootSignature: rootSignature,
|
||||
VS: _D3D12_SHADER_BYTECODE{
|
||||
pShaderBytecode: vsh.GetBufferPointer(),
|
||||
BytecodeLength: vsh.GetBufferSize(),
|
||||
},
|
||||
PS: _D3D12_SHADER_BYTECODE{
|
||||
pShaderBytecode: psh.GetBufferPointer(),
|
||||
BytecodeLength: psh.GetBufferSize(),
|
||||
},
|
||||
BlendState: _D3D12_BLEND_DESC{
|
||||
AlphaToCoverageEnable: 0,
|
||||
IndependentBlendEnable: 0,
|
||||
RenderTarget: [8]_D3D12_RENDER_TARGET_BLEND_DESC{
|
||||
{
|
||||
BlendEnable: 1,
|
||||
LogicOpEnable: 0,
|
||||
SrcBlend: blendFactorToBlend12(blend.BlendFactorSourceRGB, false),
|
||||
DestBlend: blendFactorToBlend12(blend.BlendFactorDestinationRGB, false),
|
||||
BlendOp: blendOperationToBlendOp12(blend.BlendOperationRGB),
|
||||
SrcBlendAlpha: blendFactorToBlend12(blend.BlendFactorSourceAlpha, true),
|
||||
DestBlendAlpha: blendFactorToBlend12(blend.BlendFactorDestinationAlpha, true),
|
||||
BlendOpAlpha: blendOperationToBlendOp12(blend.BlendOperationAlpha),
|
||||
LogicOp: _D3D12_LOGIC_OP_NOOP,
|
||||
RenderTargetWriteMask: writeMask,
|
||||
},
|
||||
},
|
||||
},
|
||||
SampleMask: math.MaxUint32,
|
||||
RasterizerState: _D3D12_RASTERIZER_DESC{
|
||||
FillMode: _D3D12_FILL_MODE_SOLID,
|
||||
CullMode: _D3D12_CULL_MODE_NONE,
|
||||
FrontCounterClockwise: 0,
|
||||
DepthBias: _D3D12_DEFAULT_DEPTH_BIAS,
|
||||
DepthBiasClamp: _D3D12_DEFAULT_DEPTH_BIAS_CLAMP,
|
||||
SlopeScaledDepthBias: _D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
|
||||
DepthClipEnable: 0,
|
||||
MultisampleEnable: 0,
|
||||
AntialiasedLineEnable: 0,
|
||||
ForcedSampleCount: 0,
|
||||
ConservativeRaster: _D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF,
|
||||
},
|
||||
DepthStencilState: depthStencilDesc,
|
||||
InputLayout: _D3D12_INPUT_LAYOUT_DESC{
|
||||
pInputElementDescs: &inputElementDescsForDX12[0],
|
||||
NumElements: uint32(len(inputElementDescsForDX12)),
|
||||
},
|
||||
PrimitiveTopologyType: _D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
|
||||
NumRenderTargets: 1,
|
||||
RTVFormats: [8]_DXGI_FORMAT{
|
||||
rtvFormat,
|
||||
},
|
||||
DSVFormat: dsvFormat,
|
||||
SampleDesc: _DXGI_SAMPLE_DESC{
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
}
|
||||
|
||||
s, err := device.CreateGraphicsPipelineState(&psoDesc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (p *pipelineStates) releaseConstantBuffers(frameIndex int) {
|
||||
for i := range p.constantBuffers[frameIndex] {
|
||||
p.constantBuffers[frameIndex][i].Unmap(0, nil)
|
||||
p.constantBuffers[frameIndex][i].Release()
|
||||
p.constantBuffers[frameIndex][i] = nil
|
||||
p.constantBufferMaps[frameIndex][i] = 0
|
||||
}
|
||||
p.constantBuffers[frameIndex] = p.constantBuffers[frameIndex][:0]
|
||||
p.constantBufferMaps[frameIndex] = p.constantBufferMaps[frameIndex][:0]
|
||||
}
|
||||
|
||||
func (p *pipelineStates) resetConstantBuffers(frameIndex int) {
|
||||
p.constantBuffers[frameIndex] = p.constantBuffers[frameIndex][:0]
|
||||
p.constantBufferMaps[frameIndex] = p.constantBufferMaps[frameIndex][:0]
|
||||
}
|
||||
Generated
Vendored
+195
@@ -0,0 +1,195 @@
|
||||
// Copyright 2023 The Ebitengine Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package directx
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||
)
|
||||
|
||||
type shader11 struct {
|
||||
graphics *graphics11
|
||||
id graphicsdriver.ShaderID
|
||||
uniformTypes []shaderir.Type
|
||||
uniformOffsets []int
|
||||
vertexShaderBlob *_ID3DBlob
|
||||
pixelShaderBlob *_ID3DBlob
|
||||
|
||||
inputLayout *_ID3D11InputLayout
|
||||
vertexShader *_ID3D11VertexShader
|
||||
pixelShader *_ID3D11PixelShader
|
||||
constantBuffer *_ID3D11Buffer
|
||||
}
|
||||
|
||||
func (s *shader11) ID() graphicsdriver.ShaderID {
|
||||
return s.id
|
||||
}
|
||||
|
||||
func (s *shader11) Dispose() {
|
||||
s.graphics.removeShader(s)
|
||||
}
|
||||
|
||||
func (s *shader11) disposeImpl() {
|
||||
if s.pixelShaderBlob != nil {
|
||||
s.pixelShaderBlob.Release()
|
||||
s.pixelShaderBlob = nil
|
||||
}
|
||||
if s.vertexShaderBlob != nil {
|
||||
count := s.vertexShaderBlob.Release()
|
||||
if count == 0 {
|
||||
for k, v := range vertexShaderCache {
|
||||
if v == s.vertexShaderBlob {
|
||||
delete(vertexShaderCache, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
s.vertexShader = nil
|
||||
}
|
||||
if s.inputLayout != nil {
|
||||
s.inputLayout.Release()
|
||||
s.inputLayout = nil
|
||||
}
|
||||
if s.vertexShader != nil {
|
||||
s.vertexShader.Release()
|
||||
s.vertexShader = nil
|
||||
}
|
||||
if s.pixelShader != nil {
|
||||
s.pixelShader.Release()
|
||||
s.pixelShader = nil
|
||||
}
|
||||
if s.constantBuffer != nil {
|
||||
s.constantBuffer.Release()
|
||||
s.constantBuffer = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (s *shader11) use(uniforms []uint32, srcs [graphics.ShaderImageCount]*image11) error {
|
||||
vs, err := s.ensureVertexShader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.graphics.deviceContext.VSSetShader(vs, nil)
|
||||
|
||||
ps, err := s.ensurePixelShader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.graphics.deviceContext.PSSetShader(ps, nil)
|
||||
|
||||
il, err := s.ensureInputLayout()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.graphics.deviceContext.IASetInputLayout(il)
|
||||
|
||||
cb, err := s.ensureConstantBuffer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.graphics.deviceContext.VSSetConstantBuffers(0, []*_ID3D11Buffer{cb})
|
||||
s.graphics.deviceContext.PSSetConstantBuffers(0, []*_ID3D11Buffer{cb})
|
||||
|
||||
// Send the constant buffer data.
|
||||
uniforms = adjustUniforms(s.uniformTypes, s.uniformOffsets, uniforms)
|
||||
var mapped _D3D11_MAPPED_SUBRESOURCE
|
||||
if err := s.graphics.deviceContext.Map(unsafe.Pointer(cb), 0, _D3D11_MAP_WRITE_DISCARD, 0, &mapped); err != nil {
|
||||
return err
|
||||
}
|
||||
copy(unsafe.Slice((*uint32)(mapped.pData), len(uniforms)), uniforms)
|
||||
s.graphics.deviceContext.Unmap(unsafe.Pointer(cb), 0)
|
||||
|
||||
// Set the render sources.
|
||||
var srvs [graphics.ShaderImageCount]*_ID3D11ShaderResourceView
|
||||
for i, src := range srcs {
|
||||
if src == nil {
|
||||
continue
|
||||
}
|
||||
srv, err := src.getShaderResourceView()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srvs[i] = srv
|
||||
}
|
||||
s.graphics.deviceContext.PSSetShaderResources(0, srvs[:])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *shader11) ensureInputLayout() (*_ID3D11InputLayout, error) {
|
||||
if s.inputLayout != nil {
|
||||
return s.inputLayout, nil
|
||||
}
|
||||
|
||||
i, err := s.graphics.device.CreateInputLayout(inputElementDescsForDX11, s.vertexShaderBlob.GetBufferPointer(), s.vertexShaderBlob.GetBufferSize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.inputLayout = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (s *shader11) ensureVertexShader() (*_ID3D11VertexShader, error) {
|
||||
if s.vertexShader != nil {
|
||||
return s.vertexShader, nil
|
||||
}
|
||||
|
||||
vs, err := s.graphics.device.CreateVertexShader(s.vertexShaderBlob.GetBufferPointer(), s.vertexShaderBlob.GetBufferSize(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.vertexShader = vs
|
||||
return vs, nil
|
||||
}
|
||||
|
||||
func (s *shader11) ensurePixelShader() (*_ID3D11PixelShader, error) {
|
||||
if s.pixelShader != nil {
|
||||
return s.pixelShader, nil
|
||||
}
|
||||
|
||||
ps, err := s.graphics.device.CreatePixelShader(s.pixelShaderBlob.GetBufferPointer(), s.pixelShaderBlob.GetBufferSize(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.pixelShader = ps
|
||||
return ps, nil
|
||||
}
|
||||
|
||||
func alignUp16(x uint32) uint32 {
|
||||
if x%16 == 0 {
|
||||
return x
|
||||
}
|
||||
return x + 16 - (x % 16)
|
||||
}
|
||||
|
||||
func (s *shader11) ensureConstantBuffer() (*_ID3D11Buffer, error) {
|
||||
if s.constantBuffer != nil {
|
||||
return s.constantBuffer, nil
|
||||
}
|
||||
|
||||
cb, err := s.graphics.device.CreateBuffer(&_D3D11_BUFFER_DESC{
|
||||
ByteWidth: alignUp16(uint32(constantBufferSize(s.uniformTypes, s.uniformOffsets)) * 4),
|
||||
Usage: _D3D11_USAGE_DYNAMIC,
|
||||
BindFlags: uint32(_D3D11_BIND_CONSTANT_BUFFER),
|
||||
CPUAccessFlags: uint32(_D3D11_CPU_ACCESS_WRITE),
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.constantBuffer = cb
|
||||
return cb, nil
|
||||
}
|
||||
Generated
Vendored
+89
@@ -0,0 +1,89 @@
|
||||
// Copyright 2023 The Ebitengine Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package directx
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||
)
|
||||
|
||||
type pipelineStateKey struct {
|
||||
blend graphicsdriver.Blend
|
||||
stencilMode stencilMode
|
||||
screen bool
|
||||
}
|
||||
|
||||
type shader12 struct {
|
||||
graphics *graphics12
|
||||
id graphicsdriver.ShaderID
|
||||
uniformTypes []shaderir.Type
|
||||
uniformOffsets []int
|
||||
vertexShader *_ID3DBlob
|
||||
pixelShader *_ID3DBlob
|
||||
|
||||
pipelineStates map[pipelineStateKey]*_ID3D12PipelineState
|
||||
}
|
||||
|
||||
func (s *shader12) ID() graphicsdriver.ShaderID {
|
||||
return s.id
|
||||
}
|
||||
|
||||
func (s *shader12) Dispose() {
|
||||
s.graphics.removeShader(s)
|
||||
}
|
||||
|
||||
func (s *shader12) disposeImpl() {
|
||||
for c, p := range s.pipelineStates {
|
||||
p.Release()
|
||||
delete(s.pipelineStates, c)
|
||||
}
|
||||
|
||||
if s.pixelShader != nil {
|
||||
s.pixelShader.Release()
|
||||
s.pixelShader = nil
|
||||
}
|
||||
if s.vertexShader != nil {
|
||||
count := s.vertexShader.Release()
|
||||
if count == 0 {
|
||||
for k, v := range vertexShaderCache {
|
||||
if v == s.vertexShader {
|
||||
delete(vertexShaderCache, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
s.vertexShader = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (s *shader12) pipelineState(blend graphicsdriver.Blend, stencilMode stencilMode, screen bool) (*_ID3D12PipelineState, error) {
|
||||
key := pipelineStateKey{
|
||||
blend: blend,
|
||||
stencilMode: stencilMode,
|
||||
screen: screen,
|
||||
}
|
||||
if state, ok := s.pipelineStates[key]; ok {
|
||||
return state, nil
|
||||
}
|
||||
|
||||
state, err := s.graphics.pipelineStates.newPipelineState(s.graphics.device, s.vertexShader, s.pixelShader, blend, stencilMode, screen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if s.pipelineStates == nil {
|
||||
s.pipelineStates = map[pipelineStateKey]*_ID3D12PipelineState{}
|
||||
}
|
||||
s.pipelineStates[key] = state
|
||||
return state, nil
|
||||
}
|
||||
Generated
Vendored
+262
@@ -0,0 +1,262 @@
|
||||
// Copyright 2023 The Ebitengine Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package directx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||
)
|
||||
|
||||
var vertexShaderCache = map[string]*_ID3DBlob{}
|
||||
|
||||
func compileShader(vs, ps string) (vsh, psh *_ID3DBlob, ferr error) {
|
||||
var flag uint32 = uint32(_D3DCOMPILE_OPTIMIZATION_LEVEL3)
|
||||
|
||||
defer func() {
|
||||
if ferr == nil {
|
||||
return
|
||||
}
|
||||
if vsh != nil {
|
||||
vsh.Release()
|
||||
}
|
||||
if psh != nil {
|
||||
psh.Release()
|
||||
}
|
||||
}()
|
||||
|
||||
var wg errgroup.Group
|
||||
|
||||
// Vertex shaders are likely the same. If so, reuse the same _ID3DBlob.
|
||||
if v, ok := vertexShaderCache[vs]; ok {
|
||||
// Increment the reference count not to release this object unexpectedly.
|
||||
// The value will be removed when the count reached 0.
|
||||
// See (*Shader).disposeImpl.
|
||||
v.AddRef()
|
||||
vsh = v
|
||||
} else {
|
||||
defer func() {
|
||||
if ferr == nil {
|
||||
vertexShaderCache[vs] = vsh
|
||||
}
|
||||
}()
|
||||
wg.Go(func() error {
|
||||
v, err := _D3DCompile([]byte(vs), "shader", nil, nil, "VSMain", "vs_4_0", flag, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("directx: D3DCompile for VSMain failed, original source: %s, %w", vs, err)
|
||||
}
|
||||
vsh = v
|
||||
return nil
|
||||
})
|
||||
}
|
||||
wg.Go(func() error {
|
||||
p, err := _D3DCompile([]byte(ps), "shader", nil, nil, "PSMain", "ps_4_0", flag, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("directx: D3DCompile for PSMain failed, original source: %s, %w", ps, err)
|
||||
}
|
||||
psh = p
|
||||
return nil
|
||||
})
|
||||
|
||||
if err := wg.Wait(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func constantBufferSize(uniformTypes []shaderir.Type, uniformOffsets []int) int {
|
||||
var size int
|
||||
for i, typ := range uniformTypes {
|
||||
if size < uniformOffsets[i]/4 {
|
||||
size = uniformOffsets[i] / 4
|
||||
}
|
||||
|
||||
switch typ.Main {
|
||||
case shaderir.Float:
|
||||
size += 1
|
||||
case shaderir.Int:
|
||||
size += 1
|
||||
case shaderir.Vec2, shaderir.IVec2:
|
||||
size += 2
|
||||
case shaderir.Vec3, shaderir.IVec3:
|
||||
size += 3
|
||||
case shaderir.Vec4, shaderir.IVec4:
|
||||
size += 4
|
||||
case shaderir.Mat2:
|
||||
size += 6
|
||||
case shaderir.Mat3:
|
||||
size += 11
|
||||
case shaderir.Mat4:
|
||||
size += 16
|
||||
case shaderir.Array:
|
||||
// Each element is aligned to the boundary.
|
||||
switch typ.Sub[0].Main {
|
||||
case shaderir.Float:
|
||||
size += 4*(typ.Length-1) + 1
|
||||
case shaderir.Int:
|
||||
size += 4*(typ.Length-1) + 1
|
||||
case shaderir.Vec2, shaderir.IVec2:
|
||||
size += 4*(typ.Length-1) + 2
|
||||
case shaderir.Vec3, shaderir.IVec3:
|
||||
size += 4*(typ.Length-1) + 3
|
||||
case shaderir.Vec4, shaderir.IVec4:
|
||||
size += 4 * typ.Length
|
||||
case shaderir.Mat2:
|
||||
size += 8*(typ.Length-1) + 6
|
||||
case shaderir.Mat3:
|
||||
size += 12*(typ.Length-1) + 11
|
||||
case shaderir.Mat4:
|
||||
size += 16 * typ.Length
|
||||
default:
|
||||
panic(fmt.Sprintf("directx: not implemented type for uniform variables: %s", typ.String()))
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("directx: not implemented type for uniform variables: %s", typ.String()))
|
||||
}
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
func adjustUniforms(uniformTypes []shaderir.Type, uniformOffsets []int, uniforms []uint32) []uint32 {
|
||||
var fs []uint32
|
||||
var idx int
|
||||
for i, typ := range uniformTypes {
|
||||
if len(fs) < uniformOffsets[i]/4 {
|
||||
fs = append(fs, make([]uint32, uniformOffsets[i]/4-len(fs))...)
|
||||
}
|
||||
|
||||
n := typ.Uint32Count()
|
||||
switch typ.Main {
|
||||
case shaderir.Float:
|
||||
fs = append(fs, uniforms[idx:idx+1]...)
|
||||
case shaderir.Int:
|
||||
fs = append(fs, uniforms[idx:idx+1]...)
|
||||
case shaderir.Vec2, shaderir.IVec2:
|
||||
fs = append(fs, uniforms[idx:idx+2]...)
|
||||
case shaderir.Vec3, shaderir.IVec3:
|
||||
fs = append(fs, uniforms[idx:idx+3]...)
|
||||
case shaderir.Vec4, shaderir.IVec4:
|
||||
fs = append(fs, uniforms[idx:idx+4]...)
|
||||
case shaderir.Mat2:
|
||||
fs = append(fs,
|
||||
uniforms[idx+0], uniforms[idx+2], 0, 0,
|
||||
uniforms[idx+1], uniforms[idx+3],
|
||||
)
|
||||
case shaderir.Mat3:
|
||||
fs = append(fs,
|
||||
uniforms[idx+0], uniforms[idx+3], uniforms[idx+6], 0,
|
||||
uniforms[idx+1], uniforms[idx+4], uniforms[idx+7], 0,
|
||||
uniforms[idx+2], uniforms[idx+5], uniforms[idx+8],
|
||||
)
|
||||
case shaderir.Mat4:
|
||||
if i == graphics.ProjectionMatrixUniformVariableIndex {
|
||||
// In DirectX, the NDC's Y direction (upward) and the framebuffer's Y direction (downward) don't
|
||||
// match. Then, the Y direction must be inverted.
|
||||
// Invert the sign bits as float32 values.
|
||||
fs = append(fs,
|
||||
uniforms[idx+0], uniforms[idx+4], uniforms[idx+8], uniforms[idx+12],
|
||||
uniforms[idx+1]^(1<<31), uniforms[idx+5]^(1<<31), uniforms[idx+9]^(1<<31), uniforms[idx+13]^(1<<31),
|
||||
uniforms[idx+2], uniforms[idx+6], uniforms[idx+10], uniforms[idx+14],
|
||||
uniforms[idx+3], uniforms[idx+7], uniforms[idx+11], uniforms[idx+15],
|
||||
)
|
||||
} else {
|
||||
fs = append(fs,
|
||||
uniforms[idx+0], uniforms[idx+4], uniforms[idx+8], uniforms[idx+12],
|
||||
uniforms[idx+1], uniforms[idx+5], uniforms[idx+9], uniforms[idx+13],
|
||||
uniforms[idx+2], uniforms[idx+6], uniforms[idx+10], uniforms[idx+14],
|
||||
uniforms[idx+3], uniforms[idx+7], uniforms[idx+11], uniforms[idx+15],
|
||||
)
|
||||
}
|
||||
case shaderir.Array:
|
||||
// Each element is aligned to the boundary.
|
||||
switch typ.Sub[0].Main {
|
||||
case shaderir.Float:
|
||||
for j := 0; j < typ.Length; j++ {
|
||||
fs = append(fs, uniforms[idx+j])
|
||||
if j < typ.Length-1 {
|
||||
fs = append(fs, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
case shaderir.Int:
|
||||
for j := 0; j < typ.Length; j++ {
|
||||
fs = append(fs, uniforms[idx+j])
|
||||
if j < typ.Length-1 {
|
||||
fs = append(fs, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
case shaderir.Vec2, shaderir.IVec2:
|
||||
for j := 0; j < typ.Length; j++ {
|
||||
fs = append(fs, uniforms[idx+2*j:idx+2*(j+1)]...)
|
||||
if j < typ.Length-1 {
|
||||
fs = append(fs, 0, 0)
|
||||
}
|
||||
}
|
||||
case shaderir.Vec3, shaderir.IVec3:
|
||||
for j := 0; j < typ.Length; j++ {
|
||||
fs = append(fs, uniforms[idx+3*j:idx+3*(j+1)]...)
|
||||
if j < typ.Length-1 {
|
||||
fs = append(fs, 0)
|
||||
}
|
||||
}
|
||||
case shaderir.Vec4, shaderir.IVec4:
|
||||
fs = append(fs, uniforms[idx:idx+4*typ.Length]...)
|
||||
case shaderir.Mat2:
|
||||
for j := 0; j < typ.Length; j++ {
|
||||
u := uniforms[idx+4*j : idx+4*(j+1)]
|
||||
fs = append(fs,
|
||||
u[0], u[2], 0, 0,
|
||||
u[1], u[3], 0, 0,
|
||||
)
|
||||
}
|
||||
if typ.Length > 0 {
|
||||
fs = fs[:len(fs)-2]
|
||||
}
|
||||
case shaderir.Mat3:
|
||||
for j := 0; j < typ.Length; j++ {
|
||||
u := uniforms[idx+9*j : idx+9*(j+1)]
|
||||
fs = append(fs,
|
||||
u[0], u[3], u[6], 0,
|
||||
u[1], u[4], u[7], 0,
|
||||
u[2], u[5], u[8], 0,
|
||||
)
|
||||
}
|
||||
if typ.Length > 0 {
|
||||
fs = fs[:len(fs)-1]
|
||||
}
|
||||
case shaderir.Mat4:
|
||||
for j := 0; j < typ.Length; j++ {
|
||||
u := uniforms[idx+16*j : idx+16*(j+1)]
|
||||
fs = append(fs,
|
||||
u[0], u[4], u[8], u[12],
|
||||
u[1], u[5], u[9], u[13],
|
||||
u[2], u[6], u[10], u[14],
|
||||
u[3], u[7], u[11], u[15],
|
||||
)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("directx: not implemented type for uniform variables: %s", typ.String()))
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("directx: not implemented type for uniform variables: %s", typ.String()))
|
||||
}
|
||||
|
||||
idx += n
|
||||
}
|
||||
return fs
|
||||
}
|
||||
Reference in New Issue
Block a user